//==============================================================================
//
//  File        : mmpf_scaler.c
//  Description : Firmware Display Control Function
//  Author      : Penguin Torng
//  Revision    : 1.0
//
//==============================================================================

#include "includes_fw.h"
#include "lib_retina.h"
#include "mmp_reg_gbl.h"
#include "mmp_reg_scaler.h"
#include "mmp_reg_vif.h" 
#include "mmpf_scaler.h"
#include "mmpf_hif.h"
#if defined(DSC_MP3_P_FW)||defined(VIDEO_AMR_R_FW)||defined(VIDEO_AAC_R_FW)||(SENSOR_EN)
#include "mmpf_sensor.h"
#include "mmpf_rawproc.h"
#endif
#include "mmps_dsc.h"
#include "mmps_3gprecd.h"
#include "mmpf_usbpccam.h"
#if XU_FRAMEBASE_CAPTURE
#include "mmpf_usbuvc.h"
#endif

/** @addtogroup MMPF_Scaler
@{
*/
#define USB_LYNC_TEST_MODE 0
static MMPF_SCALER_ZOOM_INFO m_scalerZoomInfo[TOTAL_SCALER_PATH];
static MMPF_SCALER_PANTILT_INFO m_scalerPanTiltInfo[TOTAL_SCALER_PATH];
MMP_UBYTE      gbZoomPathSel;
MMP_UBYTE      gbPanTiltPathSel ;

extern	MMP_UBYTE	m_gbSystemCoreID;
extern  MMPS_3GPRECD_VIDEO_FORMAT m_VideoFmt;

//==============================================================================
//
//                              VARIABLES
//
//==============================================================================


//==============================================================================
//
//                              FUNCTION PROTOTYPES
//
//==============================================================================

//------------------------------------------------------------------------------
//  Function    : MMPF_Scaler_SetEngine
//  Description :
//------------------------------------------------------------------------------
#if (CUSTOMER == PNS)
MMP_USHORT X_Start=0,Y_Start=0;
MMP_UBYTE CROP_EN=0;
#endif
#if (CUSTOMER ==QDR)
extern H264_FORMAT_TYPE gbCurH264Type;
#endif
MMP_ERR MMPF_Scaler_SetEngine(MMP_BOOL bUserdefine, MMPF_SCALER_PATH pathsel,
                        MMPF_SCALER_FIT_RANGE *fitrange, MMPF_SCALER_GRABCONTROL *grabctl)
{
    AITPS_SCAL   pSCAL    = AITC_BASE_SCAL;
    MMP_USHORT  y_scale, x_scale;
    MMP_ULONG	max_scale_width;
    MMP_USHORT  unscale_width, unscale_height;
    AIT_REG_W   *OprGrabInHStart, *OprGrabInHEnd, *OprGrabInVStart, *OprGrabInVEnd;
    AIT_REG_W   *OprGrabOutHStart, *OprGrabOutHEnd, *OprGrabOutVStart, *OprGrabOutVEnd;
    AIT_REG_B   *OprNh, *OprMh, *OprNv, *OprMv;
    AIT_REG_B   *OprHWeight, *OprVWeight;
    AIT_REG_B   *OprScaleCtl;

    if (pathsel == MMPF_SCALER_PATH_0) {
        OprScaleCtl     = &(pSCAL->SCAL_SCAL_0_CTL);
        OprGrabInHStart = &(pSCAL->SCAL_GRAB_SCAL_0_H_ST);
        OprGrabInHEnd   = &(pSCAL->SCAL_GRAB_SCAL_0_H_ED);
        OprGrabInVStart = &(pSCAL->SCAL_GRAB_SCAL_0_V_ST);
        OprGrabInVEnd   = &(pSCAL->SCAL_GRAB_SCAL_0_V_ED);
        OprGrabOutHStart= &(pSCAL->SCAL_GRAB_OUT_0_H_ST);
        OprGrabOutHEnd  = &(pSCAL->SCAL_GRAB_OUT_0_H_ED);
        OprGrabOutVStart= &(pSCAL->SCAL_GRAB_OUT_0_V_ST);
        OprGrabOutVEnd  = &(pSCAL->SCAL_GRAB_OUT_0_V_ED);
        OprNh           = &(pSCAL->SCAL_SCAL_0_H_N);
        OprMh           = &(pSCAL->SCAL_SCAL_0_H_M);
        OprNv           = &(pSCAL->SCAL_SCAL_0_V_N);
        OprMv           = &(pSCAL->SCAL_SCAL_0_V_M);
        OprHWeight      = &(pSCAL->SCAL_SCAL_0_H_WT);
        OprVWeight      = &(pSCAL->SCAL_SCAL_0_V_WT);
    }
    else if (pathsel == MMPF_SCALER_PATH_1) {
        OprScaleCtl     = &(pSCAL->SCAL_SCAL_1_CTL);
        OprGrabInHStart = &(pSCAL->SCAL_GRAB_SCAL_1_H_ST);
        OprGrabInHEnd   = &(pSCAL->SCAL_GRAB_SCAL_1_H_ED);
        OprGrabInVStart = &(pSCAL->SCAL_GRAB_SCAL_1_V_ST);
        OprGrabInVEnd   = &(pSCAL->SCAL_GRAB_SCAL_1_V_ED);
        OprGrabOutHStart= &(pSCAL->SCAL_GRAB_OUT_1_H_ST);
        OprGrabOutHEnd  = &(pSCAL->SCAL_GRAB_OUT_1_H_ED);
        OprGrabOutVStart= &(pSCAL->SCAL_GRAB_OUT_1_V_ST);
        OprGrabOutVEnd  = &(pSCAL->SCAL_GRAB_OUT_1_V_ED);
        OprNh           = &(pSCAL->SCAL_SCAL_1_H_N);
        OprMh           = &(pSCAL->SCAL_SCAL_1_H_M);
        OprNv           = &(pSCAL->SCAL_SCAL_1_V_N);
        OprMv           = &(pSCAL->SCAL_SCAL_1_V_M);
        OprHWeight      = &(pSCAL->SCAL_SCAL_1_H_WT);
        OprVWeight      = &(pSCAL->SCAL_SCAL_1_V_WT);
    }
    else {
        OprScaleCtl     = &(pSCAL->SCAL_SCAL_2_CTL);
        OprGrabInHStart = &(pSCAL->SCAL_GRAB_SCAL_2_H_ST);
        OprGrabInHEnd   = &(pSCAL->SCAL_GRAB_SCAL_2_H_ED);
        OprGrabInVStart = &(pSCAL->SCAL_GRAB_SCAL_2_V_ST);
        OprGrabInVEnd   = &(pSCAL->SCAL_GRAB_SCAL_2_V_ED);
        OprGrabOutHStart= &(pSCAL->SCAL_GRAB_OUT_2_H_ST);
        OprGrabOutHEnd  = &(pSCAL->SCAL_GRAB_OUT_2_H_ED);
        OprGrabOutVStart= &(pSCAL->SCAL_GRAB_OUT_2_V_ST);
        OprGrabOutVEnd  = &(pSCAL->SCAL_GRAB_OUT_2_V_ED);
        OprNh           = &(pSCAL->SCAL_SCAL_2_H_N);
        OprMh           = &(pSCAL->SCAL_SCAL_2_H_M);
        OprNv           = &(pSCAL->SCAL_SCAL_2_V_N);
        OprMv           = &(pSCAL->SCAL_SCAL_2_V_M);
        OprHWeight      = &(pSCAL->SCAL_SCAL_2_H_WT);
        OprVWeight      = &(pSCAL->SCAL_SCAL_2_V_WT);
    }

    if (bUserdefine == MMP_TRUE) {
        if(fitrange==0) {
    		*OprGrabInHStart = grabctl->usStartX;
    		*OprGrabInHEnd   = grabctl->usEndX;
    		*OprGrabInVStart = grabctl->usStartY;
    		*OprGrabInVEnd   = grabctl->usEndY;

            return MMP_ERR_NONE;
        }
#if (CUSTOMER == PNS)
		if((gFramebaseCap.format==1)&&(grabctl->usEndX!=1280)&&(CROP_EN==1)) {
			MMP_USHORT tmp = grabctl->usStartX - 1;
			grabctl->usStartX -= tmp;
			grabctl->usEndX -= tmp;
			if(X_Start>(fitrange->usInWidth-grabctl->usEndX))
				X_Start = fitrange->usInWidth - grabctl->usEndX;
			grabctl->usStartX += X_Start;
			grabctl->usEndX += X_Start;
			
			tmp = grabctl->usStartY - 1;
			grabctl->usStartY -= tmp;
			grabctl->usEndY -= tmp;
			if(Y_Start>(fitrange->usInHeight-grabctl->usEndY))
				Y_Start = fitrange->usInHeight - grabctl->usEndY;
			grabctl->usStartY += Y_Start;
			grabctl->usEndY += Y_Start;
			
			CROP_EN = 0;
			grabctl->usScaleN = grabctl->usScaleM;
			dbg_printf(3, "## grab=X:%d-%d Y:%d-%d\r\n\r\n", grabctl->usStartX, grabctl->usEndX, grabctl->usStartY, grabctl->usEndY);
		}
		if(CROP_EN==2)
			CROP_EN = 0;
#endif
    }
    else {  // bUserdefine == MMP_FALSE
        grabctl->usScaleM = fitrange->usFitResol;
#if (CUSTOMER == PNS)
        if((gFramebaseCap.format==1)&&(CROP_EN==1)) {	//Format:YUY2 not to scale
            grabctl->usScaleN = grabctl->usScaleM;
        } else
#endif
        {
            y_scale = (fitrange->usOutHeight * grabctl->usScaleM + fitrange->usInHeight - 1) / fitrange->usInHeight;
            x_scale = (fitrange->usOutWidth * grabctl->usScaleM + fitrange->usInWidth - 1) / fitrange->usInWidth;
            if (fitrange->fitmode == MMPF_SCALER_FITMODE_OUT) {
                if (x_scale > y_scale)
                    grabctl->usScaleN = x_scale;
                else
                    grabctl->usScaleN = y_scale;
            }
            else if (fitrange->fitmode == MMPF_SCALER_FITMODE_IN) {
    			RTNA_DBG_Str(3, "MMPF_SCALER_FITMODE_IN not support\r\n");
            }
        }
#if (CUSTOMER == ANW)
        grabctl->usScaleNV = y_scale;
        grabctl->usScaleNH = x_scale;
        grabctl->usStartX = (fitrange->usInWidth * grabctl->usScaleNH / grabctl->usScaleM
                                - fitrange->usOutWidth) / 2 + 1;
        grabctl->usEndX = grabctl->usStartX + fitrange->usOutWidth - 1;
        grabctl->usStartY = (fitrange->usInHeight * grabctl->usScaleNV / grabctl->usScaleM
                        - fitrange->usOutHeight) / 2 + 1;
        grabctl->usEndY = grabctl->usStartY + fitrange->usOutHeight - 1;
#else
        grabctl->usStartX = (fitrange->usInWidth * grabctl->usScaleN / grabctl->usScaleM
                                - fitrange->usOutWidth) / 2 + 1;
        grabctl->usEndX = grabctl->usStartX + fitrange->usOutWidth - 1;
        grabctl->usStartY = (fitrange->usInHeight * grabctl->usScaleN / grabctl->usScaleM
                        - fitrange->usOutHeight) / 2 + 1;
        grabctl->usEndY = grabctl->usStartY + fitrange->usOutHeight - 1;
#endif
    }

	if (pathsel == MMPF_SCALER_PATH_0) {
        max_scale_width = SCALER_PATH0_MAX_WIDTH;

    	*(AIT_REG_B *)&(pSCAL->SCAL_DNSAMP_SCAL_0_H) = SCAL_DNSAMP_NONE;
    	*(AIT_REG_B *)&(pSCAL->SCAL_DNSAMP_SCAL_0_V) = SCAL_DNSAMP_NONE;
    	*(AIT_REG_B *)&(pSCAL->SCAL_DNSAMP_OUT_0_H) = SCAL_DNSAMP_NONE;
    	*(AIT_REG_B *)&(pSCAL->SCAL_DNSAMP_OUT_0_V) = SCAL_DNSAMP_NONE;
	}
	else if (pathsel == MMPF_SCALER_PATH_1) {
        max_scale_width = SCALER_PATH1_MAX_WIDTH;

    	*(AIT_REG_B *)&(pSCAL->SCAL_DNSAMP_SCAL_1_H) = SCAL_DNSAMP_NONE;
    	*(AIT_REG_B *)&(pSCAL->SCAL_DNSAMP_SCAL_1_V) = SCAL_DNSAMP_NONE;
    	*(AIT_REG_B *)&(pSCAL->SCAL_DNSAMP_OUT_1_H) = SCAL_DNSAMP_NONE;
    	*(AIT_REG_B *)&(pSCAL->SCAL_DNSAMP_OUT_1_V) = SCAL_DNSAMP_NONE;
    }
    else {
        max_scale_width = SCALER_PATH2_MAX_WIDTH;

    	*(AIT_REG_B *)&(pSCAL->SCAL_DNSAMP_SCAL_2_H) = SCAL_DNSAMP_NONE;
    	*(AIT_REG_B *)&(pSCAL->SCAL_DNSAMP_SCAL_2_V) = SCAL_DNSAMP_NONE;
    	*(AIT_REG_B *)&(pSCAL->SCAL_DNSAMP_OUT_2_H) = SCAL_DNSAMP_NONE;
    	*(AIT_REG_B *)&(pSCAL->SCAL_DNSAMP_OUT_2_V) = SCAL_DNSAMP_NONE;
    }

	*(AIT_REG_B *)((MMP_ULONG)&(pSCAL->SCAL_EDGE_0_CTL)) |= SCAL_EDGE_BYPASS;
	*(AIT_REG_B *)((MMP_ULONG)&(pSCAL->SCAL_EDGE_1_CTL)) |= SCAL_EDGE_BYPASS;
	*(AIT_REG_B *)((MMP_ULONG)&(pSCAL->SCAL_EDGE_2_CTL)) |= SCAL_EDGE_BYPASS;

    (*OprScaleCtl) &= ~(SCAL_SCAL_BYPASS);

    if (grabctl->usScaleN > grabctl->usScaleM) {
	    //FIXME, vsn_v2 (*OprScaleCtl) |=  (SCAL_SCAL_DBL_FIFO|SCAL_SCAL_UP_CONT);
    }
    else {
	    //FIXME, vsn_v2 (*OprScaleCtl) &=  ~(SCAL_SCAL_DBL_FIFO|SCAL_SCAL_UP_CONT);
    }

#if (CUSTOMER == ANW)
    *OprNh  = grabctl->usScaleNH;
    *OprMh  = grabctl->usScaleM;
    *OprNv  = grabctl->usScaleNV;
    *OprMv  = grabctl->usScaleM;
#else
    *OprNh  = grabctl->usScaleN;
    *OprMh  = grabctl->usScaleM;
    *OprNv  = grabctl->usScaleN;
    *OprMv  = grabctl->usScaleM;
#endif

    (*OprHWeight) &= ~(SCAL_SCAL_WT_AVG);
    (*OprVWeight) &= ~(SCAL_SCAL_WT_AVG);

	if ((fitrange->usInWidth * grabctl->usScaleN / grabctl->usScaleM > max_scale_width)||(grabctl->usScaleN > grabctl->usScaleM)){
        if((grabctl->usScaleN > grabctl->usScaleM)){    //scale up function: UP((length_h-1)*Nh/Mh) * UP((length_v-1)*Nv/Mv)
			//Gason@patch for scaling up 
            unscale_width = 1 + ((grabctl->usEndX - grabctl->usStartX ) * grabctl->usScaleM ) / grabctl->usScaleN;
		    unscale_height = 1 + ((grabctl->usEndY - grabctl->usStartY ) * grabctl->usScaleM ) / grabctl->usScaleN;

            //Gason@patch for scaling up 
            *OprNh = grabctl->usScaleN+1;
            *OprNv = grabctl->usScaleN+1;
           	//*(AIT_REG_W *)((MMP_ULONG)&(pSCAL->SCAL_SCAL_0_H_N) + ((pathsel)?6:0)) = grabctl->usScaleN+1;
			//*(AIT_REG_W *)((MMP_ULONG)&(pSCAL->SCAL_SCAL_0_V_N) + ((pathsel)?6:0)) = grabctl->usScaleN+1;
        }
        else {  //scale down function: DOWN((length_h)*Nh/Mh) * DOWN((length)*Nv/Mv)
		    unscale_width = ((grabctl->usEndX - grabctl->usStartX + 1) * grabctl->usScaleM + (grabctl->usScaleN - 1)) / grabctl->usScaleN;
		    unscale_height = ((grabctl->usEndY - grabctl->usStartY + 1) * grabctl->usScaleM + (grabctl->usScaleN - 1)) / grabctl->usScaleN;
        }

        #if (DSC_GRAB_CENTER)
        *OprGrabInHStart    = (fitrange->usInWidth-unscale_width)/2 + 1;
        *OprGrabInHEnd      = *OprGrabInHStart + unscale_width - 1;
        *OprGrabInVStart    = (fitrange->usInHeight-unscale_height)/2 + 1;
        *OprGrabInVEnd      = *OprGrabInVStart + unscale_height - 1;
        #else
        *OprGrabInHStart    = (grabctl->usStartX*grabctl->usScaleM + grabctl->usScaleN -1)/grabctl->usScaleN;
        *OprGrabInHEnd      = *OprGrabInHStart + unscale_width - 1;
        *OprGrabInVStart    = (grabctl->usStartY*grabctl->usScaleM + grabctl->usScaleN -1)/grabctl->usScaleN;
        *OprGrabInVEnd      = *OprGrabInVStart + unscale_height - 1;
        #endif

		*OprGrabOutHStart   = 1;
		*OprGrabOutHEnd     = grabctl->usEndX - grabctl->usStartX + 1;
		*OprGrabOutVStart   = 1;
		*OprGrabOutVEnd     = grabctl->usEndY - grabctl->usStartY + 1;
	}
	else {
        *OprGrabInHStart    = 1;
        *OprGrabInHEnd      = fitrange->usInWidth;
        *OprGrabInVStart    = 1;
        *OprGrabInVEnd      = fitrange->usInHeight;

		#if (DSC_GRAB_CENTER)
		unscale_width = (fitrange->usInWidth * grabctl->usScaleN)/grabctl->usScaleM;
		unscale_height = (fitrange->usInHeight * grabctl->usScaleN)/grabctl->usScaleM;

		*OprGrabOutHStart   = (unscale_width- (grabctl->usEndX - grabctl->usStartX + 1))/2 + 1;
		*OprGrabOutHEnd     = *OprGrabOutHStart + (grabctl->usEndX - grabctl->usStartX);
		*OprGrabOutVStart   = (unscale_height- (grabctl->usEndY - grabctl->usStartY + 1))/2 + 1;
		*OprGrabOutVEnd     = *OprGrabOutVStart + (grabctl->usEndY - grabctl->usStartY);
		#else
		*OprGrabOutHStart   = grabctl->usStartX;
		*OprGrabOutHEnd     = grabctl->usEndX;
		*OprGrabOutVStart   = grabctl->usStartY;
		*OprGrabOutVEnd     = grabctl->usEndY;
		#endif
    }
 
    if ((*OprNh)*5 < (*OprMh)*3) {
        *OprHWeight = (*OprNh) >> 1;
        *OprVWeight = (*OprNv) >> 1;
    }
    else {
        *OprHWeight = 0;
        *OprVWeight = 0;
    }

#if 0
	//ISP ask to keep for test, do not remove
	//kyle test ; bypass scaler;
	if(pathsel == MMPF_SCALER_PATH_0){
		*OprNh = 0x3c;
		*OprMh = 0x3c;
		*OprNv = 0x3c;
		*OprMv = 0x3c;
		*OprGrabOutHStart = 5;//(1280 - 640) / 2;
		*OprGrabOutHEnd = *OprGrabOutHStart + 640 - 1;
		*OprGrabOutVStart = 5;// (720 - 480) / 2;
		*OprGrabOutVEnd = *OprGrabOutVStart + 480 - 1;
	}
#endif

#if 0
    dbg_printf(3, "\r\n[%d]OprScale Ctl = 0x%X\r\nGrabInH:%d-%d V:%d-%d\r\n", pathsel, *OprScaleCtl, *OprGrabInHStart, *OprGrabInHEnd, *OprGrabInVStart, *OprGrabInVEnd);
    dbg_printf(3, "GrabOutH:%d-%d V:%d-%d\r\n", *OprGrabOutHStart, *OprGrabOutHEnd, *OprGrabOutVStart, *OprGrabOutVEnd);

    dbg_printf(3, "N/M H:%d/%d V:%d/%d\r\n", *OprNh, *OprMh, *OprNv, *OprMv);

    dbg_printf(3, "grab=X:%d-%d Y:%d-%d N/M:%d/%d\r\n\r\n", grabctl->usStartX, grabctl->usEndX, grabctl->usStartY, grabctl->usEndY, grabctl->usScaleN, grabctl->usScaleM);
#endif

   return MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPDF_Scaler_SetLPF
//  Description : 
//------------------------------------------------------------------------------
/** @brief The function set the LPF coefficient according to the grab control
		
The function calculates the best grab parameter..
@param[in] pathsel the scaling path in Scaler
@param[in] fitrange the fit range parameters
@param[in] grabctl the grab control parameters
@return It reports the status of the operation.
*/
MMP_ERR MMPF_Scaler_SetLPF(MMPF_SCALER_PATH pathsel, MMPF_SCALER_FIT_RANGE *fitrange,
                            MMPF_SCALER_GRABCONTROL *grabctl)
{
    AITPS_SCAL   pSCAL    = AITC_BASE_SCAL;
    MMP_ULONG	max_scale_width;
    AIT_REG_W   *OprGrabInHStart, *OprGrabInHEnd;
    AIT_REG_W   *OprGrabInVStart, *OprGrabInVEnd;
    AIT_REG_B   *OprNh, *OprMh, *OprNv, *OprMv;
    AIT_REG_B   *OprHWeight, *OprVWeight;

    max_scale_width = LPF_MAX_WIDTH;

    if (pathsel == MMPF_SCALER_PATH_0) {
        OprGrabInHStart = &(pSCAL->SCAL_GRAB_SCAL_0_H_ST);
        OprGrabInHEnd   = &(pSCAL->SCAL_GRAB_SCAL_0_H_ED);
        OprGrabInVStart = &(pSCAL->SCAL_GRAB_SCAL_0_V_ST);
        OprGrabInVEnd   = &(pSCAL->SCAL_GRAB_SCAL_0_V_ED);
        OprNh           = &(pSCAL->SCAL_SCAL_0_H_N);
        OprMh           = &(pSCAL->SCAL_SCAL_0_H_M);
        OprNv           = &(pSCAL->SCAL_SCAL_0_V_N);
        OprMv           = &(pSCAL->SCAL_SCAL_0_V_M);
        OprHWeight      = &(pSCAL->SCAL_SCAL_0_H_WT);
        OprVWeight      = &(pSCAL->SCAL_SCAL_0_V_WT);

        pSCAL->SCAL_LPF_AUTO_CTL    |= SCAL_LPF0_EN;

        pSCAL->SCAL_GRAB_LPF_H_ST   = 1;
        pSCAL->SCAL_GRAB_LPF_H_ED   = fitrange->usInWidth;
        pSCAL->SCAL_GRAB_LPF_V_ST   = 1;
        pSCAL->SCAL_GRAB_LPF_V_ED   = fitrange->usInHeight;

        pSCAL->SCAL_DNSAMP_LPF_H    = SCAL_DNSAMP_NONE;
        pSCAL->SCAL_DNSAMP_LPF_V    = SCAL_DNSAMP_NONE;

        pSCAL->SCAL_LPF_CTL         = SCAL_LPF_BYPASS;
        pSCAL->SCAL_LPF_SCAL_CTL    = SCAL_LPF_DNSAMP_NONE;
    }
    else if (pathsel == MMPF_SCALER_PATH_1) {
        OprGrabInHStart = &(pSCAL->SCAL_GRAB_SCAL_1_H_ST);
        OprGrabInHEnd   = &(pSCAL->SCAL_GRAB_SCAL_1_H_ED);
        OprGrabInVStart = &(pSCAL->SCAL_GRAB_SCAL_1_V_ST);
        OprGrabInVEnd   = &(pSCAL->SCAL_GRAB_SCAL_1_V_ED);
        OprNh           = &(pSCAL->SCAL_SCAL_1_H_N);
        OprMh           = &(pSCAL->SCAL_SCAL_1_H_M);
        OprNv           = &(pSCAL->SCAL_SCAL_1_V_N);
        OprMv           = &(pSCAL->SCAL_SCAL_1_V_M);
        OprHWeight      = &(pSCAL->SCAL_SCAL_1_H_WT);
        OprVWeight      = &(pSCAL->SCAL_SCAL_1_V_WT);

        pSCAL->SCAL_LPF_AUTO_CTL    |= SCAL_LPF1_EN;	

        pSCAL->SCAL_GRAB_LPF1_H_ST  = 1;
        pSCAL->SCAL_GRAB_LPF1_H_ED  = fitrange->usInWidth;
        pSCAL->SCAL_GRAB_LPF1_V_ST  = 1;
        pSCAL->SCAL_GRAB_LPF1_V_ED  = fitrange->usInHeight;

        pSCAL->SCAL_DNSAMP_LPF1_H   = SCAL_DNSAMP_NONE;
        pSCAL->SCAL_DNSAMP_LPF1_V   = SCAL_DNSAMP_NONE;

        pSCAL->SCAL_LPF1_SCAL_CTL   = SCAL_LPF_DNSAMP_NONE;
    }
    else {
        OprGrabInHStart = &(pSCAL->SCAL_GRAB_SCAL_2_H_ST);
        OprGrabInHEnd   = &(pSCAL->SCAL_GRAB_SCAL_2_H_ED);
        OprGrabInVStart = &(pSCAL->SCAL_GRAB_SCAL_2_V_ST);
        OprGrabInVEnd   = &(pSCAL->SCAL_GRAB_SCAL_2_V_ED);
        OprNh           = &(pSCAL->SCAL_SCAL_2_H_N);
        OprMh           = &(pSCAL->SCAL_SCAL_2_H_M);
        OprNv           = &(pSCAL->SCAL_SCAL_2_V_N);
        OprMv           = &(pSCAL->SCAL_SCAL_2_V_M);
        OprHWeight      = &(pSCAL->SCAL_SCAL_2_H_WT);
        OprVWeight      = &(pSCAL->SCAL_SCAL_2_V_WT);

        pSCAL->SCAL_LPF2_AUTO_CTL    |= SCAL_LPF2_EN;	

        pSCAL->SCAL_GRAB_LPF2_H_ST  = 1;
        pSCAL->SCAL_GRAB_LPF2_H_ED  = fitrange->usInWidth;
        pSCAL->SCAL_GRAB_LPF2_V_ST  = 1;
        pSCAL->SCAL_GRAB_LPF2_V_ED  = fitrange->usInHeight;

        pSCAL->SCAL_DNSAMP_LPF2_H   = SCAL_DNSAMP_NONE;
        pSCAL->SCAL_DNSAMP_LPF2_V   = SCAL_DNSAMP_NONE;

        pSCAL->SCAL_LPF2_SCAL_CTL   = SCAL_LPF_DNSAMP_NONE;
    }

    if (fitrange->usInWidth > max_scale_width) {
    	if (pathsel == MMPF_SCALER_PATH_0) {
    	    pSCAL->SCAL_LPF_AUTO_CTL &= ~SCAL_LPF0_EN;
    	}
    	else if (pathsel == MMPF_SCALER_PATH_1) {
    	    pSCAL->SCAL_LPF_AUTO_CTL &= ~SCAL_LPF1_EN;
    	}
    	else {
    	    pSCAL->SCAL_LPF2_AUTO_CTL &= ~SCAL_LPF2_EN;
    	}
        return	MMP_ERR_NONE;                      
    }

	if (grabctl->usScaleN >= grabctl->usScaleM) {
        #if (CHIP == VSN_V2)
        if (pathsel == MMPF_SCALER_PATH_0) {
            pSCAL->SCAL_LPF_CTL  = SCAL_LPF_BYPASS;
        }
        else if (pathsel == MMPF_SCALER_PATH_1) {
            pSCAL->SCAL_LPF1_SCAL_CTL  = SCAL_LPF_BYPASS;
        }
        else if (pathsel == MMPF_SCALER_PATH_2) {
            pSCAL->SCAL_LPF2_SCAL_CTL  = SCAL_LPF_BYPASS;
        }
        #endif
	} 
   	else if (2*(grabctl->usScaleN) >= grabctl->usScaleM) {	//	1->1/2
        #if (CHIP == VSN_V2)
        if (pathsel == MMPF_SCALER_PATH_0) {
            pSCAL->SCAL_LPF_CTL  = SCAL_LPF_BYPASS;
        }
        else if (pathsel == MMPF_SCALER_PATH_1) {
            pSCAL->SCAL_LPF1_SCAL_CTL  = SCAL_LPF_BYPASS;
        }
        else if (pathsel == MMPF_SCALER_PATH_2) {
            pSCAL->SCAL_LPF2_SCAL_CTL  = SCAL_LPF_BYPASS;
        }
        #endif
	}
	else if (4*(grabctl->usScaleN) >= grabctl->usScaleM) {	//	1/2->1/4
		//*(AIT_REG_W *)((MMP_ULONG)&(pSCAL->SCAL_GRAB_SCAL_0_H_ST) + (pathsel << 3)) = 
		//    ALIGN2(*(AIT_REG_W *)((MMP_ULONG)&(pSCAL->SCAL_GRAB_SCAL_0_H_ST) + (pathsel << 3))) >> 1;
		//*(AIT_REG_W *)((MMP_ULONG)&(pSCAL->SCAL_GRAB_SCAL_0_V_ST) + (pathsel << 3)) = 
		//    ALIGN2(*(AIT_REG_W *)((MMP_ULONG)&(pSCAL->SCAL_GRAB_SCAL_0_V_ST) + (pathsel << 3))) >> 1;
		//*(AIT_REG_W *)((MMP_ULONG)&(pSCAL->SCAL_GRAB_SCAL_0_H_ED) + (pathsel << 3)) = 
		//    ALIGN2(*(AIT_REG_W *)((MMP_ULONG)&(pSCAL->SCAL_GRAB_SCAL_0_H_ED) + (pathsel << 3))) >> 1;
		//*(AIT_REG_W *)((MMP_ULONG)&(pSCAL->SCAL_GRAB_SCAL_0_V_ED) + (pathsel << 3)) = 
		//    ALIGN2(*(AIT_REG_W *)((MMP_ULONG)&(pSCAL->SCAL_GRAB_SCAL_0_V_ED) + (pathsel << 3))) >> 1;
        (*OprGrabInHStart)  = ALIGN2(*OprGrabInHStart)  >> 1;
        (*OprGrabInHEnd)    = ALIGN2(*OprGrabInHEnd)    >> 1;
        (*OprGrabInVStart)  = ALIGN2(*OprGrabInVStart)  >> 1;
        (*OprGrabInVEnd)    = ALIGN2(*OprGrabInVEnd)    >> 1;

        //(*(AIT_REG_B *)((MMP_ULONG)&(pSCAL->SCAL_SCAL_0_H_N) + ((pathsel)?6:0))) <<= 1; 
        //(*(AIT_REG_B *)((MMP_ULONG)&(pSCAL->SCAL_SCAL_0_V_N) + ((pathsel)?6:0))) <<= 1; 
        (*OprNh) = (*OprNh) << 1;
        (*OprNv) = (*OprNv) << 1;

        if (pathsel == MMPF_SCALER_PATH_0) {
            pSCAL->SCAL_LPF_SCAL_CTL = SCAL_LPF_DNSAMP_1_2 | 
                                       SCAL_LPF_Y_L1_EN | 
                                       SCAL_LPF_UV_EN;
        }
        else if (pathsel == MMPF_SCALER_PATH_1) {
            pSCAL->SCAL_LPF1_SCAL_CTL = SCAL_LPF_DNSAMP_1_2 | 
                                        SCAL_LPF_Y_L1_EN | 
                                        SCAL_LPF_UV_EN;
        }
        else {
            pSCAL->SCAL_LPF2_SCAL_CTL = SCAL_LPF_DNSAMP_1_2 | 
                                        SCAL_LPF_Y_L1_EN | 
                                        SCAL_LPF_UV_EN;
        }
	}
	else {	//	1/4
		//*(AIT_REG_W *)((MMP_ULONG)&(pSCAL->SCAL_GRAB_SCAL_0_H_ST) + (pathsel << 3)) = 
		//		ALIGN4(*(AIT_REG_W *)((MMP_ULONG)&(pSCAL->SCAL_GRAB_SCAL_0_H_ST) + (pathsel << 3))) >> 2;
		//*(AIT_REG_W *)((MMP_ULONG)&(pSCAL->SCAL_GRAB_SCAL_0_V_ST) + (pathsel << 3)) = 
		//		ALIGN4(*(AIT_REG_W *)((MMP_ULONG)&(pSCAL->SCAL_GRAB_SCAL_0_V_ST) + (pathsel << 3))) >> 2;
		//*(AIT_REG_W *)((MMP_ULONG)&(pSCAL->SCAL_GRAB_SCAL_0_H_ED) + (pathsel << 3)) = 
		//		ALIGN4(*(AIT_REG_W *)((MMP_ULONG)&(pSCAL->SCAL_GRAB_SCAL_0_H_ED) + (pathsel << 3))) >> 2;
		//*(AIT_REG_W *)((MMP_ULONG)&(pSCAL->SCAL_GRAB_SCAL_0_V_ED) + (pathsel << 3)) = 
		//		ALIGN4(*(AIT_REG_W *)((MMP_ULONG)&(pSCAL->SCAL_GRAB_SCAL_0_V_ED) + (pathsel << 3))) >> 2;
        (*OprGrabInHStart)  = ALIGN4(*OprGrabInHStart)  >> 2;
        (*OprGrabInHEnd)    = ALIGN4(*OprGrabInHEnd)    >> 2;
        (*OprGrabInVStart)  = ALIGN4(*OprGrabInVStart)  >> 2;
        (*OprGrabInVEnd)    = ALIGN4(*OprGrabInVEnd)    >> 2;

        //(*(AIT_REG_B *)((MMP_ULONG)&(pSCAL->SCAL_SCAL_0_H_N) + ((pathsel)?6:0)) ) <<= 2; 
        //(*(AIT_REG_B *)((MMP_ULONG)&(pSCAL->SCAL_SCAL_0_V_N) + ((pathsel)?6:0)) ) <<= 2; 
        (*OprNh) = (*OprNh) << 2;
        (*OprNv) = (*OprNv) << 2;

        if (pathsel == MMPF_SCALER_PATH_0) {
            pSCAL->SCAL_LPF_SCAL_CTL = SCAL_LPF_DNSAMP_1_4 | 
                                       SCAL_LPF_Y_L1_EN | 
                                       SCAL_LPF_Y_L2_EN |
                                       SCAL_LPF_UV_EN;
	    }
        else if (pathsel == MMPF_SCALER_PATH_1) {
            pSCAL->SCAL_LPF1_SCAL_CTL = SCAL_LPF_DNSAMP_1_4 |
                                        SCAL_LPF_Y_L1_EN |
                                        SCAL_LPF_Y_L2_EN |
                                        SCAL_LPF_UV_EN;
        }
        else {
            pSCAL->SCAL_LPF2_SCAL_CTL = SCAL_LPF_DNSAMP_1_4 |
                                        SCAL_LPF_Y_L1_EN |
                                        SCAL_LPF_Y_L2_EN |
                                        SCAL_LPF_UV_EN;
        }
	}

	if (pathsel == MMPF_SCALER_PATH_0) {
		if ((pSCAL->SCAL_LPF_CTL) || (pSCAL->SCAL_LPF_SCAL_CTL))
			pSCAL->SCAL_LPF_AUTO_CTL |=SCAL_LPF0_EN;
		else
			pSCAL->SCAL_LPF_AUTO_CTL &= (~SCAL_LPF0_EN);
	}
	else if (pathsel == MMPF_SCALER_PATH_1) {
		if (pSCAL->SCAL_LPF1_SCAL_CTL)
			pSCAL->SCAL_LPF_AUTO_CTL |= SCAL_LPF1_EN;
		else
			pSCAL->SCAL_LPF_AUTO_CTL &= (~SCAL_LPF1_EN);
	}
	else {
		if (pSCAL->SCAL_LPF2_SCAL_CTL)
			pSCAL->SCAL_LPF2_AUTO_CTL |= SCAL_LPF2_EN;
		else
			pSCAL->SCAL_LPF2_AUTO_CTL &= (~SCAL_LPF2_EN);
	}

    if ((*OprNh)*5 < (*OprMh)*3) {
        *OprHWeight = (*OprNh) >> 1;
        *OprVWeight = (*OprNv) >> 1;
    }
    else {
        *OprHWeight = 0;
        *OprVWeight = 0;
    }

    return  MMP_ERR_NONE;    
}

MMP_ERR MMPF_Scaler_SetOutputFormat(MMPF_SCALER_PATH pathsel, MMPF_SCALER_COLORMODE outcolor)
{
    AITPS_SCAL      pSCAL = AITC_BASE_SCAL;
    AIT_REG_B       *pOutCtlOpr;

    if (pathsel == MMPF_SCALER_PATH_0) {
        pOutCtlOpr = (AIT_REG_B *)&(pSCAL->SCAL_OUT_0_CTL);
    }
    else if (pathsel == MMPF_SCALER_PATH_1) {
        pOutCtlOpr = (AIT_REG_B *)&(pSCAL->SCAL_OUT_1_CTL);
    }
    else {
        pOutCtlOpr = (AIT_REG_B *)&(pSCAL->SCAL_OUT_2_CTL);
    }

    switch (outcolor) {
    #if 0
    case MMPF_SCALER_COLOR_RGB565:
        (*pOutCtlOpr) &= ~SCAL_OUT_YUV_EN;
        //MMPH_HIF_RegSetB(SCAL_OUT_0_CTL + offset, SCAL_OUT_RGB_EN |
        //    SCAL_OUT_FMT_RGB565 |
		//	SCAL_OUT_DITHER_EN |
		//	SCAL_OUT_RGB);
        break;
    #endif
	case MMPF_SCALER_COLOR_YUV422:
	    (*pOutCtlOpr) |= (SCAL_OUT_YUV_EN|SCAL_OUT_FMT_YUV422);
        break;	
    #if 0
    case MMPF_SCALER_COLOR_RGB888:
        MMPH_HIF_RegSetB(SCAL_OUT_0_CTL + offset, SCAL_OUT_RGB_EN |
			SCAL_OUT_FMT_RGB888 |
			SCAL_OUT_RGB);
        break;
    case MMPF_SCALER_COLOR_YUV444:
        MMPH_HIF_RegSetB(SCAL_OUT_0_CTL + offset, SCAL_OUT_YUV_EN |
            SCAL_OUT_FMT_YUV444);
        break;
    #endif
    default:
        return MMP_SCALER_ERR_PARAMETER;
    }

    return MMP_ERR_NONE;
}

#if (CHIP == VSN_V2)
static MMP_SHORT m_ScalerColorOffset_BT601[3] = {
    16, 128, 128
};
static MMP_SHORT m_ScalerColorMatrix_BT601[3][3] = {
    {219,   0,   0},
    {  0, 224,   0},
    {  0,   0, 224}
};
static MMP_SHORT m_ScalerColorClip_BT601[3][2] = {
    { 16, 235},
    { 16, 240},
    { 16, 240}
};
static MMP_SHORT m_ScalerColorOffset_ExtendBT601[3] = {
    0xED, 128, 128
};
static MMP_SHORT m_ScalerColorMatrix_ExtendBT601[3][3] = {
    {297,   0,   0},
    {  0, 290,   0},
    {  0,   0, 290}
};
static MMP_SHORT m_ScalerColorClip_ExtendBT601[3][2] = {
    { 0, 255},
    { 0, 255},
    { 0, 255}
};
#endif

MMP_ERR MMPF_Scaler_SetOutputColor(MMPF_SCALER_PATH pathsel, MMP_BOOL bEnable, MMPF_SCALER_COLRMTX_MODE MatrixMode)
{
    #if (CHIP == VSN_V2)
    AITPS_SCAL pSCAL = AITC_BASE_SCAL;
    volatile AITS_SCAL_MTX *pMtxOpr;
    volatile AITS_SCAL_COLR_CLIP *pClipOpr;
    MMP_ULONG   i;
    MMP_LONG    s_coeff;

    if (pathsel == MMPF_SCALER_PATH_0) {
        pMtxOpr = &(pSCAL->SCAL_P0_CT_MTX);
        pClipOpr = &(pSCAL->SCAL_P0_MTX_CLIP);
    }
    else if (pathsel == MMPF_SCALER_PATH_1) {
        pMtxOpr = &(pSCAL->SCAL_P1_CT_MTX);
        pClipOpr = &(pSCAL->SCAL_P1_MTX_CLIP);
    }
    else {
        pMtxOpr = &(pSCAL->SCAL_P2_CT_MTX);
        pClipOpr = &(pSCAL->SCAL_P2_MTX_CLIP);
    }

    if (bEnable) {
        switch (MatrixMode) {
        case MMPF_SCALER_COLRMTX_BT601:
            pMtxOpr->MTX_COEFF_ROW1_MSB &= ~(SCAL_MTX_COL_COEFF_MSB_MASK);
            pMtxOpr->MTX_COEFF_ROW2_MSB &= ~(SCAL_MTX_COL_COEFF_MSB_MASK);
            pMtxOpr->MTX_COEFF_ROW3_MSB &= ~(SCAL_MTX_COL_COEFF_MSB_MASK);
            for (i = 0; i < 3; i++) {
                s_coeff = SIGN_BIT_CONVERT(m_ScalerColorMatrix_BT601[0][i], 10);
                pMtxOpr->MTX_COEFF_ROW1[i] = (s_coeff & 0xFF);
                pMtxOpr->MTX_COEFF_ROW1_MSB |= (SCAL_MTX_COL_COEFF_MSB(s_coeff, i));

                s_coeff = SIGN_BIT_CONVERT(m_ScalerColorMatrix_BT601[1][i], 10);
                pMtxOpr->MTX_COEFF_ROW2[i] = (s_coeff & 0xFF);
                pMtxOpr->MTX_COEFF_ROW2_MSB |= (SCAL_MTX_COL_COEFF_MSB(s_coeff, i));

                s_coeff = SIGN_BIT_CONVERT(m_ScalerColorMatrix_BT601[2][i], 10);
                pMtxOpr->MTX_COEFF_ROW3[i] = (s_coeff & 0xFF);
                pMtxOpr->MTX_COEFF_ROW3_MSB |= (SCAL_MTX_COL_COEFF_MSB(s_coeff, i));
            }

            s_coeff = SIGN_BIT_CONVERT(m_ScalerColorOffset_BT601[0], 9);
            pMtxOpr->MTX_Y_OFST = (s_coeff & 0xFF);
            if (s_coeff & 0x100) {
                pMtxOpr->COLRMTX_CTL |= SCAL_MTX_Y_OFST_MSB;
            }
            else {
                pMtxOpr->COLRMTX_CTL &= ~(SCAL_MTX_Y_OFST_MSB);
            }

            s_coeff = SIGN_BIT_CONVERT(m_ScalerColorOffset_BT601[1], 9);
            pMtxOpr->MTX_U_OFST = (s_coeff & 0xFF);
            if (s_coeff & 0x100) {
                pMtxOpr->COLRMTX_CTL |= SCAL_MTX_U_OFST_MSB;
            }
            else {
                pMtxOpr->COLRMTX_CTL &= ~(SCAL_MTX_U_OFST_MSB);
            }

            s_coeff = SIGN_BIT_CONVERT(m_ScalerColorOffset_BT601[2], 9);
            pMtxOpr->MTX_V_OFST = (s_coeff & 0xFF);
            if (s_coeff & 0x100) {
                pMtxOpr->COLRMTX_CTL |= SCAL_MTX_V_OFST_MSB;
            }
            else {
                pMtxOpr->COLRMTX_CTL &= ~(SCAL_MTX_V_OFST_MSB);
            }

            pClipOpr->OUT_Y_MIN = m_ScalerColorClip_BT601[0][0];
            pClipOpr->OUT_Y_MAX = m_ScalerColorClip_BT601[0][1];
            pClipOpr->OUT_U_MIN = m_ScalerColorClip_BT601[1][0];
            pClipOpr->OUT_U_MAX = m_ScalerColorClip_BT601[1][1];
            pClipOpr->OUT_V_MIN = 0xF010;//m_ScalerColorClip_BT601[2][0];
            //pClipOpr->OUT_V_MAX = m_ScalerColorClip_BT601[2][1];
            break;
        case MMPF_SCALER_COLRMTX_EXTEND_BT601:
            pMtxOpr->MTX_COEFF_ROW1_MSB &= ~(SCAL_MTX_COL_COEFF_MSB_MASK);
            pMtxOpr->MTX_COEFF_ROW2_MSB &= ~(SCAL_MTX_COL_COEFF_MSB_MASK);
            pMtxOpr->MTX_COEFF_ROW3_MSB &= ~(SCAL_MTX_COL_COEFF_MSB_MASK);
            for (i = 0; i < 3; i++) {
                s_coeff = SIGN_BIT_CONVERT(m_ScalerColorMatrix_ExtendBT601[0][i], 10);
                pMtxOpr->MTX_COEFF_ROW1[i] = (s_coeff & 0xFF);
                pMtxOpr->MTX_COEFF_ROW1_MSB |= (SCAL_MTX_COL_COEFF_MSB(s_coeff, i));

                s_coeff = SIGN_BIT_CONVERT(m_ScalerColorMatrix_ExtendBT601[1][i], 10);
                pMtxOpr->MTX_COEFF_ROW2[i] = (s_coeff & 0xFF);
                pMtxOpr->MTX_COEFF_ROW2_MSB |= (SCAL_MTX_COL_COEFF_MSB(s_coeff, i));

                s_coeff = SIGN_BIT_CONVERT(m_ScalerColorMatrix_ExtendBT601[2][i], 10);
                pMtxOpr->MTX_COEFF_ROW3[i] = (s_coeff & 0xFF);
                pMtxOpr->MTX_COEFF_ROW3_MSB |= (SCAL_MTX_COL_COEFF_MSB(s_coeff, i));
            }

            //s_coeff = SIGN_BIT_CONVERT(m_ScalerColorOffset_ExtendBT601[0], 9);
            s_coeff = 0x1ED;
            pMtxOpr->MTX_Y_OFST = (s_coeff & 0xFF);
            if (s_coeff & 0x100) {
                pMtxOpr->COLRMTX_CTL |= SCAL_MTX_Y_OFST_MSB;
            }
            else {
                pMtxOpr->COLRMTX_CTL &= ~(SCAL_MTX_Y_OFST_MSB);
            }

            s_coeff = SIGN_BIT_CONVERT(m_ScalerColorOffset_ExtendBT601[1], 9);
            pMtxOpr->MTX_U_OFST = (s_coeff & 0xFF);
            if (s_coeff & 0x100) {
                pMtxOpr->COLRMTX_CTL |= SCAL_MTX_U_OFST_MSB;
            }
            else {
                pMtxOpr->COLRMTX_CTL &= ~(SCAL_MTX_U_OFST_MSB);
            }

            s_coeff = SIGN_BIT_CONVERT(m_ScalerColorOffset_ExtendBT601[2], 9);
            pMtxOpr->MTX_V_OFST = (s_coeff & 0xFF);
            if (s_coeff & 0x100) {
                pMtxOpr->COLRMTX_CTL |= SCAL_MTX_V_OFST_MSB;
            }
            else {
                pMtxOpr->COLRMTX_CTL &= ~(SCAL_MTX_V_OFST_MSB);
            }

            pClipOpr->OUT_Y_MIN = m_ScalerColorClip_ExtendBT601[0][0];
            pClipOpr->OUT_Y_MAX = m_ScalerColorClip_ExtendBT601[0][1];
            pClipOpr->OUT_U_MIN = m_ScalerColorClip_ExtendBT601[1][0];
            pClipOpr->OUT_U_MAX = m_ScalerColorClip_ExtendBT601[1][1];
            pClipOpr->OUT_V_MIN = 0xFF00;//m_ScalerColorClip_ExtendBT601[2][0];
            //pClipOpr->OUT_V_MAX = m_ScalerColorClip_ExtendBT601[2][1];
            break;
        case MMPF_SCALER_COLRMTX_FULLRANGE:
            pMtxOpr->COLRMTX_CTL &= ~(SCAL_COLRMTX_EN);
            return MMP_ERR_NONE;
        default:
            return MMP_SCALER_ERR_PARAMETER;
        }
        pMtxOpr->COLRMTX_CTL |= SCAL_COLRMTX_EN;
    }
    else {
        pMtxOpr->COLRMTX_CTL &= ~(SCAL_COLRMTX_EN);
    }

    #endif

    return MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Scaler_SetZoomParams
//  Description :
//------------------------------------------------------------------------------
MMP_ERR MMPF_Scaler_SetZoomParams(MMPF_SCALER_PATH pathsel, MMPF_SCALER_GRABCONTROL *grabctl,
                        MMP_USHORT usInputWidth, MMP_USHORT usInputHeight, MMP_USHORT usStepX, MMP_USHORT usStepY)
{
    m_scalerZoomInfo[pathsel].usStepX = usStepX;
    m_scalerZoomInfo[pathsel].usStepY = usStepY;
    m_scalerZoomInfo[pathsel].usInputWidth = usInputWidth;
    m_scalerZoomInfo[pathsel].usInputHeight = usInputHeight;
    m_scalerZoomInfo[pathsel].grabCtl = *grabctl;
#if (CUSTOMER == ANW)
    m_scalerZoomInfo[pathsel].usBaseNV = grabctl->usScaleNV;
    m_scalerZoomInfo[pathsel].usBaseNH = grabctl->usScaleNH;
#endif
    m_scalerZoomInfo[pathsel].usBaseN = grabctl->usScaleN;

    return MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Scaler_SetZoomRange
//  Description :
//------------------------------------------------------------------------------
MMP_ERR MMPF_Scaler_SetZoomRange(MMPF_SCALER_PATH pathsel, MMP_USHORT usZoomMin, MMP_USHORT usZoomMax)
{
    m_scalerZoomInfo[pathsel].usRangeMinN = usZoomMin;
    m_scalerZoomInfo[pathsel].usRangeMaxN = usZoomMax;
#if 0
        RTNA_DBG_Str3("usZoomMin = ");
        RTNA_DBG_Short3(usZoomMin);
        RTNA_DBG_Str3(" , usZoomMax = ");
        RTNA_DBG_Short3(usZoomMax);
        RTNA_DBG_Str3("\r\n");
#endif
    return MMP_ERR_NONE;
}

MMP_ERR MMPF_Scaler_SetZoomRangeEx(MMPF_SCALER_PATH pathsel, MMP_USHORT usZoomMinX, MMP_USHORT usZoomMaxX,MMP_USHORT usZoomMinY, MMP_USHORT usZoomMaxY)
{
#if USB_LYNC_TEST_MODE    
    m_scalerZoomInfo[pathsel].usRangeMinXN = usZoomMinX;
    m_scalerZoomInfo[pathsel].usRangeMaxXN = usZoomMaxX;
    m_scalerZoomInfo[pathsel].usRangeMinYN = usZoomMinY;
    m_scalerZoomInfo[pathsel].usRangeMaxYN = usZoomMaxY;
#endif    
    return MMP_ERR_NONE ;
}

MMPF_SCALER_PANTILT_INFO* MMPF_Scaler_GetCurPanTiltInfo(MMPF_SCALER_PATH PathSel)
{
    return &m_scalerPanTiltInfo[PathSel] ;
}

#if SUPPORT_DIGITAL_PAN 

//------------------------------------------------------------------------------
//  Function    : MMPF_Scaler_SetPanTiltRange
//  Description :
//------------------------------------------------------------------------------
MMP_ERR MMPF_Scaler_SetPanTiltRange(MMPF_SCALER_PATH pathsel, MMP_LONG usPanMin, MMP_LONG usPanMax, MMP_LONG usTiltMin, MMP_LONG usTiltMax, MMP_USHORT usSteps)
{
    m_scalerPanTiltInfo[pathsel].ulCurPan = usPanMin;
    m_scalerPanTiltInfo[pathsel].ulTargetPan = usPanMax;
    m_scalerPanTiltInfo[pathsel].ulCurTilt = usTiltMin;
    m_scalerPanTiltInfo[pathsel].ulTargetTilt = usTiltMax;
    m_scalerPanTiltInfo[pathsel].usStep = usSteps;   
/*
        RTNA_DBG_Str3("usPanMin = ");
        RTNA_DBG_Long3(usPanMin);
        RTNA_DBG_Str3(" , usPanMax = ");
        RTNA_DBG_Long3(usPanMax);
        RTNA_DBG_Str3("\r\n");
        RTNA_DBG_Str3("usTiltMin = ");
        RTNA_DBG_Long3(usTiltMin);
        RTNA_DBG_Str3(" , usTiltMax = ");
        RTNA_DBG_Long3(usTiltMax);
        RTNA_DBG_Str3("\r\n");
*/
    return MMP_ERR_NONE;
}


MMP_ERR MMPF_Scaler_SetPanTiltParams(MMPF_SCALER_PATH pathsel,MMP_LONG targetPan,MMP_LONG targetTilt,MMP_USHORT steps,MMP_LONG *pan_off,MMP_LONG *tilt_off)
{
    MMPF_SCALER_ZOOM_INFO  *scalerInfo ,panTiltScalerInfo ;  
    MMP_LONG   off_x,off_y ;
    MMP_USHORT limitW,limitH, grabW,grabH, actlimitW, actlimitH ;

    panTiltScalerInfo = *MMPF_Scaler_GetCurInfo(pathsel) ;
 
    if(steps==0) {
        steps = m_scalerPanTiltInfo[pathsel].usStep ;
        targetPan = m_scalerPanTiltInfo[pathsel].ulTargetPan;
        targetTilt = m_scalerPanTiltInfo[pathsel].ulTargetTilt;
        
    } else {
        m_scalerPanTiltInfo[pathsel].usStep = steps ;
    }
    if(steps==0) {
        return MMP_SCALER_ERR_PARAMETER ;
    }

#if 0
    RTNA_DBG_Str3("@ steps :"); RTNA_DBG_Short3(steps); RTNA_DBG_Str3("\r\n");
    RTNA_DBG_Str3("@ targetPan :"); RTNA_DBG_Short3(targetPan); RTNA_DBG_Str3("\r\n");
    RTNA_DBG_Str3("@ targetTilt :"); RTNA_DBG_Short3(targetTilt); RTNA_DBG_Str3("\r\n");
    RTNA_DBG_Str3("@ CurPan :"); RTNA_DBG_Short3(m_scalerPanTiltInfo[pathsel].ulCurPan); RTNA_DBG_Str3("\r\n");
    RTNA_DBG_Str3("@ CurTilt :"); RTNA_DBG_Short3(m_scalerPanTiltInfo[pathsel].ulCurTilt); RTNA_DBG_Str3("\r\n");
#endif
        
    scalerInfo = &panTiltScalerInfo;

    if(scalerInfo->grabCtl.usScaleN > scalerInfo->grabCtl.usScaleM){
        actlimitW = (scalerInfo->usInputWidth * scalerInfo->grabCtl.usScaleN)/ scalerInfo->grabCtl.usScaleM - 2;
        actlimitH = (scalerInfo->usInputHeight * scalerInfo->grabCtl.usScaleN)/ scalerInfo->grabCtl.usScaleM - 2;
        limitW = actlimitW - ((steps * scalerInfo->grabCtl.usScaleN) / scalerInfo->grabCtl.usScaleM);
        limitH = actlimitH - ((steps * scalerInfo->grabCtl.usScaleN) / scalerInfo->grabCtl.usScaleM);
    }
    else{
        actlimitW = (scalerInfo->usInputWidth * scalerInfo->grabCtl.usScaleN)/ scalerInfo->grabCtl.usScaleM;
        actlimitH = (scalerInfo->usInputHeight * scalerInfo->grabCtl.usScaleN)/ scalerInfo->grabCtl.usScaleM;
        limitW = actlimitW;
        limitH = actlimitH;
    }
    
    grabW = scalerInfo->grabCtl.usEndX - scalerInfo->grabCtl.usStartX ;
    grabH = scalerInfo->grabCtl.usEndY - scalerInfo->grabCtl.usStartY ;
    
    off_x = ( (limitW - (grabW + 1) ) ) / steps ; 
    off_y = ( (limitH - (grabH + 1) ) ) / steps ;

    *pan_off = targetPan / 3600;
    *tilt_off = targetTilt / 3600;

    if(*pan_off > 0){
        scalerInfo->grabCtl.usStartX = 1 + ((actlimitW - (grabW + 1) ) >> 1) + (off_x * (*pan_off));
        if((scalerInfo->grabCtl.usStartX + grabW) > actlimitW){
            scalerInfo->grabCtl.usStartX = actlimitW - grabW;
        }
        scalerInfo->grabCtl.usEndX = scalerInfo->grabCtl.usStartX + grabW;
        m_scalerPanTiltInfo[pathsel].usPanEnd = 0 ;
    }
    else{
        *pan_off = 0 - *pan_off;
        if((1 + ((actlimitW - (grabW + 1) ) >> 1)) > (off_x * (*pan_off))){
            scalerInfo->grabCtl.usStartX = 1 + ((actlimitW - (grabW + 1) ) >> 1) - (off_x * (*pan_off));
        }
        else{
            scalerInfo->grabCtl.usStartX = 1;
        }
        scalerInfo->grabCtl.usEndX = scalerInfo->grabCtl.usStartX + grabW;
        m_scalerPanTiltInfo[pathsel].usPanEnd = 0 ;
    }

    if(*tilt_off > 0){
        scalerInfo->grabCtl.usStartY = 1 + ((actlimitH - (grabH + 1) ) >> 1) + (off_y * (*tilt_off));
        if((scalerInfo->grabCtl.usStartY + grabH) > actlimitH){
            scalerInfo->grabCtl.usStartY = actlimitH - grabH;
        }
        scalerInfo->grabCtl.usEndY = scalerInfo->grabCtl.usStartY + grabH;
        m_scalerPanTiltInfo[pathsel].usTiltEnd = 0 ;
    }
    else{
        *tilt_off = 0 - *tilt_off;
        if((1 + ((actlimitH - (grabH + 1) ) >> 1)) > (off_y * (*tilt_off))){
            scalerInfo->grabCtl.usStartY = 1 + ((actlimitH - (grabH + 1) ) >> 1) - (off_y * (*tilt_off));
        }
        else{
            scalerInfo->grabCtl.usStartY = 1;
        }
        scalerInfo->grabCtl.usEndY = scalerInfo->grabCtl.usStartY + grabH;
        m_scalerPanTiltInfo[pathsel].usTiltEnd = 0 ;
    }
    
    #if 0
    RTNA_DBG_Str3("@ usScaleN :");RTNA_DBG_Short3(scalerInfo->grabCtl.usScaleN);RTNA_DBG_Str3(",");
    RTNA_DBG_Str3("@ usScaleM :");RTNA_DBG_Short3(scalerInfo->grabCtl.usScaleM);RTNA_DBG_Str3("\r\n");
    RTNA_DBG_Str3("@ actLimitW :"); RTNA_DBG_Short3(actlimitW); RTNA_DBG_Str3(",");
    RTNA_DBG_Str3("@ actLimitH :"); RTNA_DBG_Short3(actlimitH); RTNA_DBG_Str3("\r\n");
    RTNA_DBG_Str3("@ LimitW :"); RTNA_DBG_Short3(limitW); RTNA_DBG_Str3(",");
    RTNA_DBG_Str3("@ LimitH :"); RTNA_DBG_Short3(limitH); RTNA_DBG_Str3("\r\n");
    RTNA_DBG_Str3("@ GrabW :");  RTNA_DBG_Short3(grabW);  RTNA_DBG_Str3(",");
    RTNA_DBG_Str3("@ GrabH :");  RTNA_DBG_Short3(grabH);  RTNA_DBG_Str3("\r\n");
    RTNA_DBG_Str3("@ OffX :");RTNA_DBG_Long3(off_x);RTNA_DBG_Str3(",");
    RTNA_DBG_Str3("@ OffY :");RTNA_DBG_Long3(off_y);RTNA_DBG_Str3("\r\n");
    RTNA_DBG_Str3("@ PanOff :");RTNA_DBG_Long3(*pan_off);RTNA_DBG_Str3(",");
    RTNA_DBG_Str3("@ TiltOff :");RTNA_DBG_Long3(*tilt_off);RTNA_DBG_Str3("\r\n");
    RTNA_DBG_Str3("@ usStartX :");RTNA_DBG_Short3(scalerInfo->grabCtl.usStartX);RTNA_DBG_Str3(",");
    RTNA_DBG_Str3("@ usStartY :");RTNA_DBG_Short3(scalerInfo->grabCtl.usStartY);RTNA_DBG_Str3("\r\n");
    RTNA_DBG_Str3("@ usEndX :");RTNA_DBG_Short3(scalerInfo->grabCtl.usEndX);RTNA_DBG_Str3(",");
    RTNA_DBG_Str3("@ usEndY :");RTNA_DBG_Short3(scalerInfo->grabCtl.usEndY);RTNA_DBG_Str3("\r\n");
    #endif    

    m_scalerPanTiltInfo[pathsel].grabCtl = panTiltScalerInfo.grabCtl ;

    return MMP_ERR_NONE ;
}


MMP_ERR MMPF_Scaler_CalculatePanTiltInfo(MMPF_SCALER_PATH PathSel, MMP_LONG *pan_off, MMP_LONG *tilt_off)
{
    MMPF_SCALER_ZOOM_INFO  *scalerInfo ;
    MMP_LONG    off_x,off_y ;
    MMP_USHORT  limitW,limitH, grabW,grabH, actlimitW, actlimitH ;

    scalerInfo = MMPF_Scaler_GetCurInfo(PathSel) ;
            
    if(scalerInfo->grabCtl.usScaleN > scalerInfo->grabCtl.usScaleM){
        actlimitW = (scalerInfo->usInputWidth * scalerInfo->grabCtl.usScaleN)/ scalerInfo->grabCtl.usScaleM - 2;
        actlimitH = (scalerInfo->usInputHeight * scalerInfo->grabCtl.usScaleN)/ scalerInfo->grabCtl.usScaleM - 2;
        limitW = actlimitW - ((m_scalerPanTiltInfo[PathSel].usStep * scalerInfo->grabCtl.usScaleN) / scalerInfo->grabCtl.usScaleM);
        limitH = actlimitH - ((m_scalerPanTiltInfo[PathSel].usStep * scalerInfo->grabCtl.usScaleN) / scalerInfo->grabCtl.usScaleM);
    }
    else{
#if (CUSTOMER == ANW)
        actlimitW = (scalerInfo->usInputWidth * scalerInfo->grabCtl.usScaleNH)/ scalerInfo->grabCtl.usScaleM;
        actlimitH = (scalerInfo->usInputHeight * scalerInfo->grabCtl.usScaleNV)/ scalerInfo->grabCtl.usScaleM;
#else
        actlimitW = (scalerInfo->usInputWidth * scalerInfo->grabCtl.usScaleN)/ scalerInfo->grabCtl.usScaleM;
        actlimitH = (scalerInfo->usInputHeight * scalerInfo->grabCtl.usScaleN)/ scalerInfo->grabCtl.usScaleM;
#endif
        limitW = actlimitW;
        limitH = actlimitH;
    }

    grabW = scalerInfo->grabCtl.usEndX - scalerInfo->grabCtl.usStartX ;
    grabH = scalerInfo->grabCtl.usEndY - scalerInfo->grabCtl.usStartY ;
            
    off_x = ( (limitW - (grabW + 1) ) ) / m_scalerPanTiltInfo[PathSel].usStep ; 
    off_y = ( (limitH - (grabH + 1) ) ) / m_scalerPanTiltInfo[PathSel].usStep ;

    //JengWei@20130830 Fix Pantilt less than Step will not work issus.
    if((limitH-(grabH+1)) < m_scalerPanTiltInfo[PathSel].usStep) {
        if((limitH-(grabH+1)) > (m_scalerPanTiltInfo[PathSel].usStep>>1))
            off_y++;
    }

    *pan_off = m_scalerPanTiltInfo[PathSel].ulTargetPan / 3600;
    *tilt_off = m_scalerPanTiltInfo[PathSel].ulTargetTilt / 3600;

    if(*pan_off > 0){
        scalerInfo->grabCtl.usStartX = 1 + ((actlimitW - (grabW + 1) ) >> 1) + (off_x * (*pan_off));
        if((scalerInfo->grabCtl.usStartX + grabW) > actlimitW){
            scalerInfo->grabCtl.usStartX = actlimitW - grabW;
        }
        scalerInfo->grabCtl.usEndX = scalerInfo->grabCtl.usStartX + grabW;
        m_scalerPanTiltInfo[PathSel].usPanEnd = 0 ;
    }
    else{
        *pan_off = 0 - *pan_off;
        if((1 + ((actlimitW - (grabW + 1) ) >> 1)) > (off_x * (*pan_off))){
            scalerInfo->grabCtl.usStartX = 1 + ((actlimitW - (grabW + 1) ) >> 1) - (off_x * (*pan_off));
        }
        else{
            scalerInfo->grabCtl.usStartX = 1;
        }
        scalerInfo->grabCtl.usEndX = scalerInfo->grabCtl.usStartX + grabW;
        m_scalerPanTiltInfo[PathSel].usPanEnd = 0 ;
    }

    if(*tilt_off > 0){
        scalerInfo->grabCtl.usStartY = 1 + ((actlimitH - (grabH + 1) ) >> 1) + (off_y * (*tilt_off));
        if((scalerInfo->grabCtl.usStartY + grabH) > actlimitH){
            scalerInfo->grabCtl.usStartY = actlimitH - grabH;
        }
        scalerInfo->grabCtl.usEndY = scalerInfo->grabCtl.usStartY + grabH;
        m_scalerPanTiltInfo[PathSel].usTiltEnd = 0 ;
    }
    else{
        *tilt_off = 0 - *tilt_off;
        if((1 + ((actlimitH - (grabH + 1) ) >> 1)) > (off_y * (*tilt_off))){
            scalerInfo->grabCtl.usStartY = 1 + ((actlimitH - (grabH + 1) ) >> 1) - (off_y * (*tilt_off));
        }
        else{
            scalerInfo->grabCtl.usStartY = 1;
        }
        scalerInfo->grabCtl.usEndY = scalerInfo->grabCtl.usStartY + grabH;
        m_scalerPanTiltInfo[PathSel].usTiltEnd = 0 ;
    }

    #if 0
    RTNA_DBG_Str3("@ usScaleN :"); RTNA_DBG_Long3(scalerInfo->grabCtl.usScaleN); RTNA_DBG_Str3(",");
    RTNA_DBG_Str3("@ usScaleM :"); RTNA_DBG_Long3(scalerInfo->grabCtl.usScaleM); RTNA_DBG_Str3("\r\n");
    RTNA_DBG_Str3("@ ActLimitW :"); RTNA_DBG_Long3(actlimitW); RTNA_DBG_Str3(",");
    RTNA_DBG_Str3("@ ActLimitH :"); RTNA_DBG_Long3(actlimitH); RTNA_DBG_Str3("\r\n");
    RTNA_DBG_Str3("@ LimitW :"); RTNA_DBG_Long3(limitW); RTNA_DBG_Str3(",");
    RTNA_DBG_Str3("@ LimitH :"); RTNA_DBG_Long3(limitH); RTNA_DBG_Str3("\r\n");
    RTNA_DBG_Str3("@ GrabW :");  RTNA_DBG_Long3(grabW);  RTNA_DBG_Str3(",");
    RTNA_DBG_Str3("@ GrabH :");  RTNA_DBG_Long3(grabH);  RTNA_DBG_Str3("\r\n");
    RTNA_DBG_Str3("@ OffX :");RTNA_DBG_Long3(off_x);RTNA_DBG_Str3(",");
    RTNA_DBG_Str3("@ OffY :");RTNA_DBG_Long3(off_y);RTNA_DBG_Str3("\r\n");
    RTNA_DBG_Str3("@ PanOff :");RTNA_DBG_Long3(*pan_off);RTNA_DBG_Str3(",");
    RTNA_DBG_Str3("@ ulTargetPan :");RTNA_DBG_Long3(m_scalerPanTiltInfo[PathSel].ulTargetPan);RTNA_DBG_Str3(", ");
    RTNA_DBG_Str3("@ ulCurPan :");RTNA_DBG_Long3(m_scalerPanTiltInfo[PathSel].ulCurPan);RTNA_DBG_Str3("\r\n");
    RTNA_DBG_Str3("@ TiltOff :");RTNA_DBG_Long3(*tilt_off);RTNA_DBG_Str3(",");
    RTNA_DBG_Str3("@ ulTargetTilt :");RTNA_DBG_Long3(m_scalerPanTiltInfo[PathSel].ulTargetTilt);RTNA_DBG_Str3(", ");
    RTNA_DBG_Str3("@ ulCurTilt :");RTNA_DBG_Long3(m_scalerPanTiltInfo[PathSel].ulCurTilt);RTNA_DBG_Str3("\r\n");
           
    RTNA_DBG_Str3("@ usStartX :");RTNA_DBG_Long3(scalerInfo->grabCtl.usStartX);RTNA_DBG_Str3(",");
    RTNA_DBG_Str3("@ usStartY :");RTNA_DBG_Long3(scalerInfo->grabCtl.usStartY);RTNA_DBG_Str3("\r\n");
    RTNA_DBG_Str3("@ usEndX :");RTNA_DBG_Long3(scalerInfo->grabCtl.usEndX);RTNA_DBG_Str3(",");
    RTNA_DBG_Str3("@ usEndY :");RTNA_DBG_Long3(scalerInfo->grabCtl.usEndY);RTNA_DBG_Str3("\r\n");
    #endif

    return MMP_ERR_NONE;    
}

MMP_ERR MMPF_Scaler_SetDigitalPanTilt(MMPF_SCALER_PATH pathsel, MMP_USHORT startOP)
{
    AITPS_VIF   pVIF = AITC_BASE_VIF;
    MMP_UBYTE   vid = 0;

    gbPanTiltPathSel |= (1) << pathsel ;
    
    if(startOP == MMP_TRUE){
    
        MMPF_HIF_SetCmdStatus(IMAGE_UNDER_PANTILT);    
        //sean@2010_12_08  
	    //pVIF->VIF_INT_CPU_SR[vid]  = ( VIF_INT_FRM_END  );
	    //pVIF->VIF_INT_CPU_EN[vid] |= ( VIF_INT_FRM_END  );
	    pVIF->VIF_INT_CPU_SR[vid]  = ( VIF_INT_GRAB_END  );
	    pVIF->VIF_INT_CPU_EN[vid] |= ( VIF_INT_GRAB_END  );
	}
    return MMP_ERR_NONE ;	
}
#endif

//------------------------------------------------------------------------------
//  Function    : MMPF_Scaler_SetDigitalZoom
//  Description :
//------------------------------------------------------------------------------
MMP_ERR MMPF_Scaler_SetDigitalZoom(MMPF_SCALER_PATH pathsel, MMPF_SCALER_ZOOMDIRECTION zoomdir, 
                                              MMP_USHORT zoomrate, MMP_USHORT startOP)
{
    AITPS_VIF   pVIF = AITC_BASE_VIF;
    MMP_UBYTE   vid = 0;
//    if(startOP) {
        gbZoomPathSel |=  (1)<< pathsel;
//    }
    m_scalerZoomInfo[pathsel].direction = zoomdir;
    m_scalerZoomInfo[pathsel].usZoomRate = zoomrate;    
    
    if ((zoomdir == MMPF_SCALER_ZOOMIN) || (zoomdir == MMPF_SCALER_ZOOMOUT)) {
        if(startOP == MMP_TRUE){
		    MMPF_HIF_SetCmdStatus(IMAGE_UNDER_ZOOM);
		    //pVIF->VIF_INT_CPU_SR[vid] = ( VIF_INT_FRM_END  ) ;
		    //pVIF->VIF_INT_CPU_EN[vid] |=( VIF_INT_FRM_END  );
		    pVIF->VIF_INT_CPU_SR[vid] = ( VIF_INT_GRAB_END  ) ;
		    pVIF->VIF_INT_CPU_EN[vid] |=( VIF_INT_GRAB_END  );
        }
    }
    else if (zoomdir == MMPF_SCALER_ZOOMSTOP) {
        //RTNA_DBG_Str(3, "MMPF_Scaler_SetDigitalZoom():ZOOM_STOP_OP\r\n");
    }

    return MMP_ERR_NONE;
}

/*
MMP_ERR MMPF_Scaler_EnableZoom(MMPF_SCALER_PATH pathsel)
{
    AITPS_VIF   pVIF = AITC_BASE_VIF;
    MMP_UBYTE   vid = 0;

    gbZoomPathSel |=  (1)<< pathsel;
    MMPF_HIF_SetCmdStatus(IMAGE_UNDER_ZOOM);
    pVIF->VIF_INT_CPU_SR[vid] = ( VIF_INT_FRM_END  ) ;
    pVIF->VIF_INT_CPU_EN[vid] |=( VIF_INT_FRM_END  );
    return MMP_ERR_NONE ;
}
*/ 
//------------------------------------------------------------------------------
//  Function    : MMPF_Scaler_SetDigitalZoomOP
//  Description :
//------------------------------------------------------------------------------
MMP_ERR MMPF_Scaler_SetDigitalZoomOP(MMPF_SCALER_PATH pathsel, MMPF_SCALER_ZOOMDIRECTION zoomdir, 
                                              MMP_USHORT zoomrate)
{
    gbZoomPathSel |= (1) << pathsel;
    m_scalerZoomInfo[pathsel].direction = zoomdir;
    m_scalerZoomInfo[pathsel].usZoomRate = zoomrate;    
   
    return MMPF_Scaler_SetZoomOP();
}

#if 0
//------------------------------------------------------------------------------
//  Function    : MMPF_Scaler_AdjustSubScaler
//  Description : 
//------------------------------------------------------------------------------
MMP_ERR MMPF_Scaler_AdjustSubScaler(MMPF_SCALER_PATH mainpipe, MMPF_SCALER_PATH subpipe)
{
    MMPF_SCALER_GRABCONTROL grabctl;
    MMPF_SCALER_FIT_RANGE fitrange;

	if(m_scalerZoomInfo[mainpipe].grabCtl.usScaleN >= m_scalerZoomInfo[mainpipe].grabCtl.usScaleM){
        //do nothing
    } 
    else if (2*(m_scalerZoomInfo[mainpipe].grabCtl.usScaleN) >= m_scalerZoomInfo[mainpipe].grabCtl.usScaleM) {	//	1->1/2
        //do nothing
    }
    else if (4*(m_scalerZoomInfo[mainpipe].grabCtl.usScaleN) >= m_scalerZoomInfo[mainpipe].grabCtl.usScaleM) {	//	1/2->1/4
        fitrange.usInWidth = m_scalerZoomInfo[subpipe].usInputWidth >> 1;
        fitrange.usInHeight = m_scalerZoomInfo[subpipe].usInputHeight >> 1;
        grabctl = m_scalerZoomInfo[subpipe].grabCtl;
        grabctl.usScaleN <<= 1;
        MMPF_Scaler_SetEngine(MMP_TRUE, subpipe, &fitrange, &grabctl);
    }
    else {	//	1/4
        fitrange.usInWidth = m_scalerZoomInfo[subpipe].usInputWidth >> 2;
        fitrange.usInHeight = m_scalerZoomInfo[subpipe].usInputHeight >> 2;
        grabctl = m_scalerZoomInfo[subpipe].grabCtl;
        grabctl.usScaleN <<= 2;
        MMPF_Scaler_SetEngine(MMP_TRUE, subpipe, &fitrange, &grabctl);
    }	
    return MMP_ERR_NONE;    
}
#endif

//------------------------------------------------------------------------------
//  Function    : MMPF_Scaler_CalculateZoomInfo
//  Description : the function calculate zoom N offset and grab offset
//------------------------------------------------------------------------------
MMP_ERR MMPF_Scaler_CalculateZoomInfo(MMPF_SCALER_PATH PathSel, MMP_UBYTE  *pbN_offset)
{
#if (CUSTOMER == ANW)
    MMP_UBYTE *pbN_offsetV, *pbN_offsetH, offsettmp = 0, VHflag = 0;

    offsettmp = (m_scalerZoomInfo[PathSel].grabCtl.usScaleNV > m_scalerZoomInfo[PathSel].grabCtl.usScaleNH)?
                (m_scalerZoomInfo[PathSel].grabCtl.usScaleNV - m_scalerZoomInfo[PathSel].grabCtl.usScaleNH):
                (m_scalerZoomInfo[PathSel].grabCtl.usScaleNH - m_scalerZoomInfo[PathSel].grabCtl.usScaleNV);
    VHflag = (m_scalerZoomInfo[PathSel].grabCtl.usScaleNV > m_scalerZoomInfo[PathSel].grabCtl.usScaleNH)?
             (1):(2);

    if (m_scalerZoomInfo[PathSel].direction == MMPF_SCALER_ZOOMIN) {
        if((m_scalerZoomInfo[PathSel].grabCtl.usScaleNH == m_scalerZoomInfo[PathSel].usRangeMaxN) ||
          (m_scalerZoomInfo[PathSel].grabCtl.usScaleNV == m_scalerZoomInfo[PathSel].usRangeMaxN)) {
            RTNA_DBG_Str(3, "S-Z-I\r\n");
            gbZoomPathSel &= ~(1<<PathSel);
            return MMP_ERR_NONE;
        }
        else {
            // N (grabCtl.usScaleN) is increasing to Max N
            // (Max N - Min N) Maybe 1.>  2.=  3.< (usZoomRate)
            if (m_scalerZoomInfo[PathSel].usZoomRate > 
                (m_scalerZoomInfo[PathSel].usRangeMaxN  - 
                m_scalerZoomInfo[PathSel].grabCtl.usScaleN)) {
                *pbN_offset = m_scalerZoomInfo[PathSel].usRangeMaxN - m_scalerZoomInfo[PathSel].grabCtl.usScaleN;
                m_scalerZoomInfo[PathSel].grabCtl.usScaleN = m_scalerZoomInfo[PathSel].usRangeMaxN - offsettmp;

                if(m_scalerZoomInfo[PathSel].grabCtl.usScaleNV > m_scalerZoomInfo[PathSel].grabCtl.usScaleNH) {
                    *pbN_offsetV = m_scalerZoomInfo[PathSel].usRangeMaxN - m_scalerZoomInfo[PathSel].grabCtl.usScaleNV;
                    *pbN_offsetH = m_scalerZoomInfo[PathSel].usRangeMaxN - m_scalerZoomInfo[PathSel].grabCtl.usScaleNH - offsettmp + 1;
                    m_scalerZoomInfo[PathSel].grabCtl.usScaleNV = m_scalerZoomInfo[PathSel].usRangeMaxN;
                    m_scalerZoomInfo[PathSel].grabCtl.usScaleNH = m_scalerZoomInfo[PathSel].usRangeMaxN - offsettmp + 1;
                }
                else {
                    *pbN_offsetH = m_scalerZoomInfo[PathSel].usRangeMaxN - m_scalerZoomInfo[PathSel].grabCtl.usScaleNH;
                    *pbN_offsetV = m_scalerZoomInfo[PathSel].usRangeMaxN - m_scalerZoomInfo[PathSel].grabCtl.usScaleNV - offsettmp + 1;
                    m_scalerZoomInfo[PathSel].grabCtl.usScaleNH = m_scalerZoomInfo[PathSel].usRangeMaxN;
                    m_scalerZoomInfo[PathSel].grabCtl.usScaleNV = m_scalerZoomInfo[PathSel].usRangeMaxN - offsettmp + 1;
                }
            } 
            else {
                *pbN_offset = m_scalerZoomInfo[PathSel].usZoomRate;
                m_scalerZoomInfo[PathSel].grabCtl.usScaleN += m_scalerZoomInfo[PathSel].usZoomRate;
            }
        }
    }
    else if (m_scalerZoomInfo[PathSel].direction == MMPF_SCALER_ZOOMOUT) {
        if ((m_scalerZoomInfo[PathSel].grabCtl.usScaleNV == m_scalerZoomInfo[PathSel].usRangeMinN) ||
           (m_scalerZoomInfo[PathSel].grabCtl.usScaleNH == m_scalerZoomInfo[PathSel].usRangeMinN)) {
            RTNA_DBG_Str(3, "S-Z-O\r\n");
            gbZoomPathSel &= ~(1<<PathSel);
            return MMP_ERR_NONE;
        }
        else {
            //N (grabCtl.usScaleN) is decreasing to Min N
            // (Max N - Min N) Maybe 1.>  2.=  3.< (usZoomRate)
            if (m_scalerZoomInfo[PathSel].usZoomRate > 
                (m_scalerZoomInfo[PathSel].grabCtl.usScaleN - 
                m_scalerZoomInfo[PathSel].usRangeMinN)) {
                *pbN_offset = m_scalerZoomInfo[PathSel].grabCtl.usScaleN - m_scalerZoomInfo[PathSel].usRangeMinN;
                m_scalerZoomInfo[PathSel].grabCtl.usScaleN = m_scalerZoomInfo[PathSel].usRangeMinN;

                if(m_scalerZoomInfo[PathSel].grabCtl.usScaleNV > m_scalerZoomInfo[PathSel].grabCtl.usScaleNH) {
                    *pbN_offsetV = m_scalerZoomInfo[PathSel].grabCtl.usScaleNV - m_scalerZoomInfo[PathSel].usRangeMinN;
                    *pbN_offsetH = m_scalerZoomInfo[PathSel].grabCtl.usScaleNH - (m_scalerZoomInfo[PathSel].usRangeMinN - offsettmp);
                    m_scalerZoomInfo[PathSel].grabCtl.usScaleNV = m_scalerZoomInfo[PathSel].usRangeMinN;
                    m_scalerZoomInfo[PathSel].grabCtl.usScaleNH = m_scalerZoomInfo[PathSel].usRangeMinN - offsettmp;
                }
                else {
                    *pbN_offsetH = m_scalerZoomInfo[PathSel].grabCtl.usScaleNH - m_scalerZoomInfo[PathSel].usRangeMinN;
                    *pbN_offsetV = m_scalerZoomInfo[PathSel].grabCtl.usScaleNV - (m_scalerZoomInfo[PathSel].usRangeMinN - offsettmp);
                    m_scalerZoomInfo[PathSel].grabCtl.usScaleNH = m_scalerZoomInfo[PathSel].usRangeMinN;
                    m_scalerZoomInfo[PathSel].grabCtl.usScaleNV = m_scalerZoomInfo[PathSel].usRangeMinN - offsettmp;
                }
            }
            else {
                *pbN_offset = m_scalerZoomInfo[PathSel].usZoomRate;
                m_scalerZoomInfo[PathSel].grabCtl.usScaleN -= m_scalerZoomInfo[PathSel].usZoomRate;
            }
        }
    }
    else if (m_scalerZoomInfo[PathSel].direction == MMPF_SCALER_ZOOMSTOP) {
            gbZoomPathSel &= ~(1<<PathSel);
            return MMP_ERR_NONE;
    }

    //Calculate new grabCtl
    if (m_scalerZoomInfo[PathSel].direction == MMPF_SCALER_ZOOMIN) {
        m_scalerZoomInfo[PathSel].grabCtl.usStartX += (m_scalerZoomInfo[PathSel].usStepX * (*pbN_offsetV));
        m_scalerZoomInfo[PathSel].grabCtl.usEndX   += (m_scalerZoomInfo[PathSel].usStepX * (*pbN_offsetV));
        m_scalerZoomInfo[PathSel].grabCtl.usStartY += (m_scalerZoomInfo[PathSel].usStepY * (*pbN_offsetH));
        m_scalerZoomInfo[PathSel].grabCtl.usEndY   += (m_scalerZoomInfo[PathSel].usStepY * (*pbN_offsetH));
    }
    else if (m_scalerZoomInfo[PathSel].direction == MMPF_SCALER_ZOOMOUT) {
        m_scalerZoomInfo[PathSel].grabCtl.usStartX -= (m_scalerZoomInfo[PathSel].usStepX * (*pbN_offsetV));
        m_scalerZoomInfo[PathSel].grabCtl.usEndX   -= (m_scalerZoomInfo[PathSel].usStepX * (*pbN_offsetV));
        m_scalerZoomInfo[PathSel].grabCtl.usStartY -= (m_scalerZoomInfo[PathSel].usStepY * (*pbN_offsetH));
        m_scalerZoomInfo[PathSel].grabCtl.usEndY   -= (m_scalerZoomInfo[PathSel].usStepY * (*pbN_offsetH));
    }
#else
    if (m_scalerZoomInfo[PathSel].direction == MMPF_SCALER_ZOOMIN) {
        if (m_scalerZoomInfo[PathSel].grabCtl.usScaleN == 
             m_scalerZoomInfo[PathSel].usRangeMaxN) {
            RTNA_DBG_Str(3, "S-Z-I\r\n");
            gbZoomPathSel &= ~(1<<PathSel);
            return MMP_ERR_NONE;
        }
        else {
            // N (grabCtl.usScaleN) is increasing to Max N
            // (Max N - Min N) Maybe 1.>  2.=  3.< (usZoomRate)
            if (m_scalerZoomInfo[PathSel].usZoomRate > 
                 (m_scalerZoomInfo[PathSel].usRangeMaxN  - 
                  m_scalerZoomInfo[PathSel].grabCtl.usScaleN)) {
                *pbN_offset = m_scalerZoomInfo[PathSel].usRangeMaxN - 
                           m_scalerZoomInfo[PathSel].grabCtl.usScaleN;

                m_scalerZoomInfo[PathSel].grabCtl.usScaleN = 
                m_scalerZoomInfo[PathSel].usRangeMaxN;
            } 
            else {
                *pbN_offset = m_scalerZoomInfo[PathSel].usZoomRate;

                m_scalerZoomInfo[PathSel].grabCtl.usScaleN += 
                m_scalerZoomInfo[PathSel].usZoomRate;
            }
        }
    }
    else if (m_scalerZoomInfo[PathSel].direction == MMPF_SCALER_ZOOMOUT) {
        if (m_scalerZoomInfo[PathSel].grabCtl.usScaleN == 
             m_scalerZoomInfo[PathSel].usRangeMinN) {
            RTNA_DBG_Str(3, "S-Z-O\r\n");
            gbZoomPathSel &= ~(1<<PathSel);
            return MMP_ERR_NONE;
        }
        else {
            //N (grabCtl.usScaleN) is decreasing to Min N
            // (Max N - Min N) Maybe 1.>  2.=  3.< (usZoomRate)
            if (m_scalerZoomInfo[PathSel].usZoomRate > 
                 (m_scalerZoomInfo[PathSel].grabCtl.usScaleN - 
                  m_scalerZoomInfo[PathSel].usRangeMinN)) {
                *pbN_offset = m_scalerZoomInfo[PathSel].grabCtl.usScaleN - 
                           m_scalerZoomInfo[PathSel].usRangeMinN;
                
                m_scalerZoomInfo[PathSel].grabCtl.usScaleN = 
                m_scalerZoomInfo[PathSel].usRangeMinN;
            }
            else {
                *pbN_offset = m_scalerZoomInfo[PathSel].usZoomRate;
                
                m_scalerZoomInfo[PathSel].grabCtl.usScaleN -=
                m_scalerZoomInfo[PathSel].usZoomRate;
            }
        }
    }
    else if (m_scalerZoomInfo[PathSel].direction == MMPF_SCALER_ZOOMSTOP) {
            gbZoomPathSel &= ~(1<<PathSel);
            return MMP_ERR_NONE;
    }

    //Calculate new grabCtl
    if (m_scalerZoomInfo[PathSel].direction == MMPF_SCALER_ZOOMIN) {
        m_scalerZoomInfo[PathSel].grabCtl.usStartX += (m_scalerZoomInfo[PathSel].usStepX * (*pbN_offset));
        m_scalerZoomInfo[PathSel].grabCtl.usEndX   += (m_scalerZoomInfo[PathSel].usStepX * (*pbN_offset));
        m_scalerZoomInfo[PathSel].grabCtl.usStartY += (m_scalerZoomInfo[PathSel].usStepY * (*pbN_offset));
        m_scalerZoomInfo[PathSel].grabCtl.usEndY   += (m_scalerZoomInfo[PathSel].usStepY * (*pbN_offset));
    }
    else if (m_scalerZoomInfo[PathSel].direction == MMPF_SCALER_ZOOMOUT) {
        m_scalerZoomInfo[PathSel].grabCtl.usStartX -= (m_scalerZoomInfo[PathSel].usStepX * (*pbN_offset));
        m_scalerZoomInfo[PathSel].grabCtl.usEndX   -= (m_scalerZoomInfo[PathSel].usStepX * (*pbN_offset));
        m_scalerZoomInfo[PathSel].grabCtl.usStartY -= (m_scalerZoomInfo[PathSel].usStepY * (*pbN_offset));
        m_scalerZoomInfo[PathSel].grabCtl.usEndY   -= (m_scalerZoomInfo[PathSel].usStepY * (*pbN_offset));
    }
#endif

    return MMP_ERR_NONE;
}

#if SUPPORT_DEFAULT_ZOOM
//------------------------------------------------------------------------------
//  Function    : MMPF_Scaler_CalculateZoomInfoByDefaultZoom
//  Description : the function calculate zoom N offset and grab offset
//------------------------------------------------------------------------------
MMP_ERR MMPF_Scaler_CalculateZoomInfoByDefaultZoom(MMPF_SCALER_PATH PathSel, MMPS_DSC_ZOOM_INFO *VidZoomInfo, MMP_UBYTE  *pbN_offset)
{
    MMPF_SCALER_GRABCONTROL    tmpgrabCtl;  
    MMPF_SCALER_FIT_RANGE   fitrange;
    MMPS_3GPRECD_CONFIGS *VideoConfig;
    MMPS_3GPRECD_MODES *VideoRecMode;
    MMP_USHORT  N_target_max;
    MMP_USHORT	usModeIdx;

    VideoConfig = MMPS_3GPRECD_GetConfiguration();
    VideoRecMode = MMPS_3GPRECD_GetMode();

    usModeIdx = VideoRecMode->usVideoEncMode;

    // move to N/M = 1/1 ratio to meet TV-CAM Skype FOV specification, tomy@2010_09_17
    VidZoomInfo->usStepIndex = (DEFAULT_ZOOM_STEP);
                                                  
    N_target_max = VidZoomInfo->usZoomMin +
                  (VidZoomInfo->usZoomMax - VidZoomInfo->usZoomMin) * VidZoomInfo->usStepIndex /
                   VideoConfig->previewdata.ubVidRecdZoomStep[usModeIdx];
    if (N_target_max > VidZoomInfo->usZoomMax){
        N_target_max = VidZoomInfo->usZoomMax;
        VidZoomInfo->usStepIndex = VideoConfig->previewdata.ubVidRecdZoomStep[usModeIdx];
    }
    VidZoomInfo->usZoomNow = N_target_max;

    MMPF_Scaler_SetZoomRange(PathSel, VidZoomInfo->usZoomMin, N_target_max);

    *pbN_offset = m_scalerZoomInfo[PathSel].usRangeMaxN - m_scalerZoomInfo[PathSel].grabCtl.usScaleN;
                
    m_scalerZoomInfo[PathSel].grabCtl.usScaleN = m_scalerZoomInfo[PathSel].usRangeMaxN;

    m_scalerZoomInfo[PathSel].grabCtl.usStartX += (m_scalerZoomInfo[PathSel].usStepX * (*pbN_offset));
    m_scalerZoomInfo[PathSel].grabCtl.usEndX   += (m_scalerZoomInfo[PathSel].usStepX * (*pbN_offset));
    m_scalerZoomInfo[PathSel].grabCtl.usStartY += (m_scalerZoomInfo[PathSel].usStepY * (*pbN_offset));
    m_scalerZoomInfo[PathSel].grabCtl.usEndY   += (m_scalerZoomInfo[PathSel].usStepY * (*pbN_offset));
        
    fitrange.usInWidth = m_scalerZoomInfo[PathSel].usInputWidth;
    fitrange.usInHeight = m_scalerZoomInfo[PathSel].usInputHeight;

    tmpgrabCtl = m_scalerZoomInfo[PathSel].grabCtl;

    MMPF_Scaler_SetEngine(MMP_TRUE, PathSel, &fitrange, &tmpgrabCtl);
    MMPF_Scaler_SetLPF(PathSel, &fitrange, &tmpgrabCtl);

    return MMP_ERR_NONE;
}
#endif

MMP_ERR MMPF_Scaler_CalculateZoomInfoEx(MMPF_SCALER_PATH PathSel, MMP_UBYTE  *pbN_offsetX,MMP_UBYTE  *pbN_offsetY)
{
#if USB_LYNC_TEST_MODE

    if (m_scalerZoomInfo[PathSel].direction == MMPF_SCALER_ZOOMIN) {
        if ( (m_scalerZoomInfo[PathSel].grabCtl.usScaleXN ==  m_scalerZoomInfo[PathSel].usRangeMaxXN) &&
             (m_scalerZoomInfo[PathSel].grabCtl.usScaleYN ==  m_scalerZoomInfo[PathSel].usRangeMaxYN) ) {
           // RTNA_DBG_Str(3, "S-S-P\r\n");
            gbZoomPathSel &= ~(1<<PathSel);
            return MMP_ERR_NONE;
        }
        else {
            // N (grabCtl.usScaleN) is increasing to Max N
            // (Max N - Min N) Maybe 1.>  2.=  3.< (usZoomRate)
            if (m_scalerZoomInfo[PathSel].usZoomRate > 
                 (m_scalerZoomInfo[PathSel].usRangeMaxXN  - 
                  m_scalerZoomInfo[PathSel].grabCtl.usScaleXN)) {
                *pbN_offsetX = m_scalerZoomInfo[PathSel].usRangeMaxXN - 
                           m_scalerZoomInfo[PathSel].grabCtl.usScaleXN;
                
                m_scalerZoomInfo[PathSel].grabCtl.usScaleXN = 
                m_scalerZoomInfo[PathSel].usRangeMaxXN;
            } 
            else {
                *pbN_offsetX = m_scalerZoomInfo[PathSel].usZoomRate;
                
                m_scalerZoomInfo[PathSel].grabCtl.usScaleXN += 
                m_scalerZoomInfo[PathSel].usZoomRate;
            }
            if (m_scalerZoomInfo[PathSel].usZoomRate > 
                 (m_scalerZoomInfo[PathSel].usRangeMaxYN  - 
                  m_scalerZoomInfo[PathSel].grabCtl.usScaleYN)) {
                *pbN_offsetY = m_scalerZoomInfo[PathSel].usRangeMaxYN - 
                           m_scalerZoomInfo[PathSel].grabCtl.usScaleYN;
                
                m_scalerZoomInfo[PathSel].grabCtl.usScaleYN = 
                m_scalerZoomInfo[PathSel].usRangeMaxYN;
            } 
            else {
                *pbN_offsetY = m_scalerZoomInfo[PathSel].usZoomRate;
                
                m_scalerZoomInfo[PathSel].grabCtl.usScaleYN += 
                m_scalerZoomInfo[PathSel].usZoomRate;
            }
        }
    }
    else if (m_scalerZoomInfo[PathSel].direction == MMPF_SCALER_ZOOMOUT) {
        if ( (m_scalerZoomInfo[PathSel].grabCtl.usScaleXN == m_scalerZoomInfo[PathSel].usRangeMinXN)&&
             (m_scalerZoomInfo[PathSel].grabCtl.usScaleYN == m_scalerZoomInfo[PathSel].usRangeMinYN) ) {
            gbZoomPathSel &= ~(1<<PathSel);
            return MMP_ERR_NONE;
        }
        else {
            //N (grabCtl.usScaleN) is decreasing to Min N
            // (Max N - Min N) Maybe 1.>  2.=  3.< (usZoomRate)
            if (m_scalerZoomInfo[PathSel].usZoomRate > 
                 (m_scalerZoomInfo[PathSel].grabCtl.usScaleXN - 
                  m_scalerZoomInfo[PathSel].usRangeMinXN)) {
                *pbN_offsetX = m_scalerZoomInfo[PathSel].grabCtl.usScaleXN - 
                           m_scalerZoomInfo[PathSel].usRangeMinXN;
                
                m_scalerZoomInfo[PathSel].grabCtl.usScaleXN = 
                m_scalerZoomInfo[PathSel].usRangeMinXN;
            }
            else {
                *pbN_offsetX = m_scalerZoomInfo[PathSel].usZoomRate;
                
                m_scalerZoomInfo[PathSel].grabCtl.usScaleXN -=
                m_scalerZoomInfo[PathSel].usZoomRate;
            }

            if (m_scalerZoomInfo[PathSel].usZoomRate > 
                 (m_scalerZoomInfo[PathSel].grabCtl.usScaleYN - 
                  m_scalerZoomInfo[PathSel].usRangeMinYN)) {
                *pbN_offsetY = m_scalerZoomInfo[PathSel].grabCtl.usScaleYN - 
                           m_scalerZoomInfo[PathSel].usRangeMinYN;
                
                m_scalerZoomInfo[PathSel].grabCtl.usScaleYN = 
                m_scalerZoomInfo[PathSel].usRangeMinYN;
            }
            else {
                *pbN_offsetY = m_scalerZoomInfo[PathSel].usZoomRate;
                
                m_scalerZoomInfo[PathSel].grabCtl.usScaleYN -=
                m_scalerZoomInfo[PathSel].usZoomRate;
            }

        }
    }
    else if (m_scalerZoomInfo[PathSel].direction == MMPF_SCALER_ZOOMSTOP) {
            gbZoomPathSel &= ~(1<<PathSel);
            return MMP_ERR_NONE;
    }

    //Calculate new grabCtl
    if (m_scalerZoomInfo[PathSel].direction == MMPF_SCALER_ZOOMIN) {
        m_scalerZoomInfo[PathSel].grabCtl.usStartX += (m_scalerZoomInfo[PathSel].usStepX * (*pbN_offsetX));
        m_scalerZoomInfo[PathSel].grabCtl.usEndX   += (m_scalerZoomInfo[PathSel].usStepX * (*pbN_offsetX));
        m_scalerZoomInfo[PathSel].grabCtl.usStartY += (m_scalerZoomInfo[PathSel].usStepY * (*pbN_offsetY));
        m_scalerZoomInfo[PathSel].grabCtl.usEndY   += (m_scalerZoomInfo[PathSel].usStepY * (*pbN_offsetY));
    }
    else if (m_scalerZoomInfo[PathSel].direction == MMPF_SCALER_ZOOMOUT) {
        m_scalerZoomInfo[PathSel].grabCtl.usStartX -= (m_scalerZoomInfo[PathSel].usStepX * (*pbN_offsetX));
        m_scalerZoomInfo[PathSel].grabCtl.usEndX   -= (m_scalerZoomInfo[PathSel].usStepX * (*pbN_offsetX));
        m_scalerZoomInfo[PathSel].grabCtl.usStartY -= (m_scalerZoomInfo[PathSel].usStepY * (*pbN_offsetY));
        m_scalerZoomInfo[PathSel].grabCtl.usEndY   -= (m_scalerZoomInfo[PathSel].usStepY * (*pbN_offsetY));
    }

	dbg_printf(3,"#offX = %d,offY = %d\r\n",*pbN_offsetX,*pbN_offsetY);
#endif
    return MMP_ERR_NONE;
}

#if SUPPORT_DIGITAL_PAN 

MMP_ERR MMPF_Scaler_SetPanTiltOP(void)
{
    AITPS_VIF               pVIF = AITC_BASE_VIF;
    MMPF_SCALER_GRABCONTROL    tmpgrabCtl;  
    MMPF_SCALER_PATH    mainpipe, subpipe;
    MMP_UBYTE   vid = 0;
    MMPF_SCALER_FIT_RANGE   fitrange;
    MMP_LONG pan_off0,tilt_off0;
    MMP_LONG pan_off1,tilt_off1;
    MMP_LONG pan_off2,tilt_off2;

    /*Set Scaler pipe0*/
    if(gbPanTiltPathSel &  (1<<MMPF_SCALER_PATH_0)){
	    MMPF_Scaler_CalculatePanTiltInfo(MMPF_SCALER_PATH_0, &pan_off0, &tilt_off0);
        //PCAM_USB_PostPanTilt(MMPF_SCALER_PATH_0,pan_off0,tilt_off0);
    }

    /*Set Scaler pipe1*/
    if(gbPanTiltPathSel &  (1<<MMPF_SCALER_PATH_1)){
	    MMPF_Scaler_CalculatePanTiltInfo(MMPF_SCALER_PATH_1, &pan_off1, &tilt_off1);
        //PCAM_USB_PostPanTilt(MMPF_SCALER_PATH_1,pan_off1,tilt_off1);
    }
    
    /*Set Scaler pipe2*/
    if(gbPanTiltPathSel &  (1<<MMPF_SCALER_PATH_2)){
	    MMPF_Scaler_CalculatePanTiltInfo(MMPF_SCALER_PATH_2, &pan_off2, &tilt_off2);
        //PCAM_USB_PostPanTilt(MMPF_SCALER_PATH_1,pan_off1,tilt_off1);
    }

    if( gbPanTiltPathSel == 0 ){  
        MMPF_HIF_ClearCmdStatus(IMAGE_UNDER_PANTILT);
        //RTNA_DBG_Str(3, "Pan...End\r\n");
        if(gbZoomPathSel==0 ) {
        // sean@2010_12_08
            //pVIF->VIF_INT_CPU_EN[vid] &= ~(VIF_INT_FRM_END);
            pVIF->VIF_INT_CPU_EN[vid] &= ~(VIF_INT_GRAB_END);
        }
        return MMP_ERR_NONE;
    }
    /*adjust the LPF, scaler pipe0, pipe1 if enable both pipe*/
    else if ((gbPanTiltPathSel  ==  ((1<<MMPF_SCALER_PATH_1)|(1<<MMPF_SCALER_PATH_0))) ||
             (gbPanTiltPathSel  ==  ((1<<MMPF_SCALER_PATH_1)|(1<<MMPF_SCALER_PATH_0)|(1<<MMPF_SCALER_PATH_2))) ) {

        if ((m_scalerZoomInfo[MMPF_SCALER_PATH_0].grabCtl.usScaleM * m_scalerZoomInfo[MMPF_SCALER_PATH_1].grabCtl.usScaleN) <=
            (m_scalerZoomInfo[MMPF_SCALER_PATH_1].grabCtl.usScaleM * m_scalerZoomInfo[MMPF_SCALER_PATH_0].grabCtl.usScaleN)) {
            // pipe0 ratio is larger
            mainpipe = MMPF_SCALER_PATH_0;	
            subpipe = MMPF_SCALER_PATH_1;	
        }
        else {
            // pipe1 ratio is larger
            mainpipe = MMPF_SCALER_PATH_1;	
            subpipe = MMPF_SCALER_PATH_0;	
        }

        //RTNA_DBG_Byte(3, mainpipe);
        //RTNA_DBG_Str(3, " Scaler zoom two pipes\r\n");
        
        fitrange.usInWidth = m_scalerZoomInfo[mainpipe].usInputWidth;
        fitrange.usInHeight = m_scalerZoomInfo[mainpipe].usInputHeight;

        /*Set main pipe*/    
        tmpgrabCtl = m_scalerZoomInfo[mainpipe].grabCtl;

        //RTNA_DBG_Long(3, fitrange.usInWidth);
        //RTNA_DBG_Long(3, fitrange.usInHeight);
        //RTNA_DBG_Str(3, " Fitrange input\r\n");

        MMPF_Scaler_SetEngine(MMP_TRUE, mainpipe, &fitrange, &tmpgrabCtl);
        //MMPF_Scaler_SetEngine(MMP_TRUE, mainpipe, 0, &tmpgrabCtl);
        MMPF_Scaler_SetLPF(mainpipe, &fitrange, &tmpgrabCtl);

        /*Set sub pipe*/  
        tmpgrabCtl = m_scalerZoomInfo[subpipe].grabCtl;

        MMPF_Scaler_SetEngine(MMP_TRUE, subpipe, &fitrange, &tmpgrabCtl);
        //MMPF_Scaler_SetEngine(MMP_TRUE, subpipe, 0, &tmpgrabCtl);
        MMPF_Scaler_SetLPF(subpipe, &fitrange, &tmpgrabCtl);

        gbPanTiltPathSel = 0 ;
    }
    else {
#if (CUSTOMER == PNS)
	if(CROP_EN)
	gbPanTiltPathSel = 0 ;
#endif
        mainpipe = gbPanTiltPathSel>>1;

        fitrange.usInWidth = m_scalerZoomInfo[mainpipe].usInputWidth;
        fitrange.usInHeight = m_scalerZoomInfo[mainpipe].usInputHeight;

        tmpgrabCtl = m_scalerZoomInfo[mainpipe].grabCtl;

        MMPF_Scaler_SetEngine(MMP_TRUE, mainpipe, &fitrange, &tmpgrabCtl);
        //MMPF_Scaler_SetEngine(MMP_TRUE, mainpipe, 0, &tmpgrabCtl);
        MMPF_Scaler_SetLPF(mainpipe, &fitrange, &tmpgrabCtl);
            
        gbPanTiltPathSel = 0 ;
    }
    return MMP_ERR_NONE;
}
#endif

//------------------------------------------------------------------------------
//  Function    : MMPF_Scaler_SetZoomOP
//  Description :
//------------------------------------------------------------------------------
MMP_ERR MMPF_Scaler_SetZoomOP(void)
{
	AITPS_VIF               pVIF = AITC_BASE_VIF;

    MMP_UBYTE               N_offset=0,N_offsetX=0,N_offsetY=0;
  //  MMPF_SCALER_FIT_RANGE   fitrange;
    #if(DSC_SCALE_GRAB_IN_RAW_EN)
    MMP_BOOL                bRawPathPreview;
    MMP_BOOL                bRawStoreDownsample;
    #endif
    MMPF_SCALER_PATH    mainpipe;
    #if 0
    MMPF_SCALER_GRABCONTROL    tmpgrabCtl;
    MMPF_SCALER_PATH    subpipe;
    #endif
    MMP_UBYTE           vid = 0;
    
	//pVIF->VIF_INT_CPU_SR[vid] = ( VIF_INT_FRM_END  );
	//pVIF->VIF_INT_CPU_SR[vid] = ( VIF_INT_GRAB_END  );

	#if(DSC_SCALE_GRAB_IN_RAW_EN)
    MMPF_Sensor_GetParam(MMPF_SENSOR_RAWPATH_PREVIEW_ENABLE  , &bRawPathPreview);
    MMPF_Sensor_GetParam(MMPF_SENSOR_RAWPATH_STORE_DOWNSAMPLE, &bRawStoreDownsample);
    #endif

    /*Set Scaler pipe0*/
    if(gbZoomPathSel &  (1<<MMPF_SCALER_PATH_0)){
        if(m_scalerZoomInfo[MMPF_SCALER_PATH_0].usBaseN) {
	        MMPF_Scaler_CalculateZoomInfo(MMPF_SCALER_PATH_0, &N_offset);
	    } else {
	        MMPF_Scaler_CalculateZoomInfoEx(MMPF_SCALER_PATH_0, &N_offsetX,&N_offsetY);
	    }
    }

    /*Set Scaler pipe1*/
    if(gbZoomPathSel &  (1<<MMPF_SCALER_PATH_1)){
        if(m_scalerZoomInfo[MMPF_SCALER_PATH_1].usBaseN) {
	        MMPF_Scaler_CalculateZoomInfo(MMPF_SCALER_PATH_1, &N_offset);
	    } else {
	        MMPF_Scaler_CalculateZoomInfoEx(MMPF_SCALER_PATH_1, &N_offsetX,&N_offsetY);
	    }
    }

    /*Set Scaler pipe2*/
    if(gbZoomPathSel &  (1<<MMPF_SCALER_PATH_2)){
        if(m_scalerZoomInfo[MMPF_SCALER_PATH_2].usBaseN) {
	        MMPF_Scaler_CalculateZoomInfo(MMPF_SCALER_PATH_2, &N_offset);
	    } else {
	        MMPF_Scaler_CalculateZoomInfoEx(MMPF_SCALER_PATH_2, &N_offsetX,&N_offsetY);
	    }
    }

    /*No zoom, stop VIF interrupt*/
    if(gbZoomPathSel == 0){
        if(gbPanTiltPathSel==0) {
            //pVIF->VIF_INT_CPU_EN[vid] &= ~(VIF_INT_FRM_END);
            pVIF->VIF_INT_CPU_EN[vid] &= ~(VIF_INT_GRAB_END);
    	}
        MMPF_HIF_ClearCmdStatus(IMAGE_UNDER_ZOOM);
        return MMP_ERR_NONE;
    }
    /*adjust the LPF, scaler pipe0, pipe1 if enable both pipe*/
    else if ((gbZoomPathSel  ==  ((1<<MMPF_SCALER_PATH_1)|(1<<MMPF_SCALER_PATH_0))) || 
             (gbZoomPathSel  ==  ((1<<MMPF_SCALER_PATH_1)|(1<<MMPF_SCALER_PATH_0)|(1<<MMPF_SCALER_PATH_2))) ) {
#if 1   
        MMPF_Scaler_SetZoomSinglePipe(MMPF_SCALER_PATH_1);
        MMPF_Scaler_SetZoomSinglePipe(MMPF_SCALER_PATH_0);
#else 
        if ((m_scalerZoomInfo[MMPF_SCALER_PATH_0].grabCtl.usScaleM * m_scalerZoomInfo[MMPF_SCALER_PATH_1].grabCtl.usScaleN) <=
            (m_scalerZoomInfo[MMPF_SCALER_PATH_1].grabCtl.usScaleM * m_scalerZoomInfo[MMPF_SCALER_PATH_0].grabCtl.usScaleN)) {
            // pipe0 ratio is large
            mainpipe = MMPF_SCALER_PATH_0;	
            subpipe = MMPF_SCALER_PATH_1;	
        }
        else {
            // pipe1 ratio is large
            mainpipe = MMPF_SCALER_PATH_1;	
            subpipe = MMPF_SCALER_PATH_0;	
        }

        RTNA_DBG_Byte(3, mainpipe);
        RTNA_DBG_Str(3, " S-2\r\n");
        
        fitrange.usInWidth = m_scalerZoomInfo[mainpipe].usInputWidth;
        fitrange.usInHeight = m_scalerZoomInfo[mainpipe].usInputHeight;

        /*Set main pipe*/    
        tmpgrabCtl = m_scalerZoomInfo[mainpipe].grabCtl;
        #if(DSC_SCALE_GRAB_IN_RAW_EN)
        if ( bRawPathPreview && bRawStoreDownsample ) {
            MMPF_RAWPROC_SetZoomOffset(m_scalerZoomInfo[mainpipe].direction,(m_scalerZoomInfo[mainpipe].usStepX * N_offset));
        }
        
        if ( bRawPathPreview ) {
            MMPF_RAWPROC_SetMainPipeZoomOP(bRawStoreDownsample, m_scalerZoomInfo,mainpipe,N_offset,&fitrange,&tmpgrabCtl);
        }        
        #endif
        
        //RTNA_DBG_Long(3, fitrange.usInWidth);
        //RTNA_DBG_Long(3, fitrange.usInHeight);
        //RTNA_DBG_Str(3, " Fitrange input\r\n");
        
        MMPF_Scaler_SetEngine(MMP_TRUE, mainpipe, &fitrange, &tmpgrabCtl);
        MMPF_Scaler_SetLPF(mainpipe, &fitrange, &tmpgrabCtl);

        /*Set sub pipe*/  
        tmpgrabCtl = m_scalerZoomInfo[subpipe].grabCtl;

        #if(DSC_SCALE_GRAB_IN_RAW_EN)
        if ( bRawPathPreview ) {
            MMPF_RAWPROC_SetSubPipeZoomOP(bRawStoreDownsample, subpipe, &fitrange, &tmpgrabCtl, &m_scalerZoomInfo[mainpipe].grabCtl);
        }        
        #endif
        MMPF_Scaler_SetEngine(MMP_TRUE, subpipe, &fitrange, &tmpgrabCtl);
        #if (CHIP == P_V2) || (CHIP == VSN_V2)
        {
            MMPF_Scaler_SetLPF(subpipe, &fitrange, &tmpgrabCtl);
        }
        #endif

        
        /*Adjust LPF for two pipe*/ 
        MMPF_Scaler_AdjustSubScaler(mainpipe, subpipe);


        /*Set raw fetch line delay and pixel delay according to main pipe N, M*/  
        #if(DSC_SCALE_GRAB_IN_RAW_EN)
        if ( bRawPathPreview ) {
            MMPF_RAWPROC_CalcRawFetchTiming(mainpipe, MMPF_RAWPROC_DISTRIBUTION);
        }
        #endif
#endif
    }
    /*only one pipe zoom*/        
    else {  
        mainpipe = gbZoomPathSel>>1;
        MMPF_Scaler_SetZoomSinglePipe(mainpipe);
    }

    return MMP_ERR_NONE;
}

MMP_ERR MMPF_Scaler_SetZoomSinglePipe(MMPF_SCALER_PATH mainpipe)
{
    MMP_LONG            pan_off,tilt_off;
    MMPF_SCALER_GRABCONTROL    tmpgrabCtl;  
    MMPF_SCALER_FIT_RANGE   fitrange;
        fitrange.usInWidth = m_scalerZoomInfo[mainpipe].usInputWidth;
        fitrange.usInHeight = m_scalerZoomInfo[mainpipe].usInputHeight;

        tmpgrabCtl = m_scalerZoomInfo[mainpipe].grabCtl;

        #if(DSC_SCALE_GRAB_IN_RAW_EN)
        if ( bRawPathPreview && bRawStoreDownsample ) {
            MMPF_RAWPROC_SetZoomOffset(m_scalerZoomInfo[mainpipe].direction,(m_scalerZoomInfo[mainpipe].usStepX * N_offset));
        }
        if ( bRawPathPreview ) {
            MMPF_RAWPROC_SetMainPipeZoomOP(bRawStoreDownsample, m_scalerZoomInfo,mainpipe,N_offset,&fitrange,&tmpgrabCtl);
        }
        #endif
        
        #if SUPPORT_DIGITAL_PAN
        // sean@2010_09_20, canculate pantilt after calculate new zoom rate
        if(MMPF_Scaler_SetPanTiltParams(mainpipe,0,0,0,&pan_off,&tilt_off) == MMP_ERR_NONE) {
//            if(pan_off || tilt_off) {
                tmpgrabCtl = m_scalerPanTiltInfo[mainpipe].grabCtl;
//            } else {
//                if( (m_scalerPanTiltInfo[mainpipe].usPanEnd==2 ) || (m_scalerPanTiltInfo[mainpipe].usTiltEnd==2)) {
//                    tmpgrabCtl = m_scalerPanTiltInfo[mainpipe].grabCtl; 
//                }
//            }
        }
        #endif
        
        #if 0
        dbg_printf(3, "SetSinglePipe %d\r\n", mainpipe);
        dbg_printf(3, "fitrange In %dx%d, Out%dx%d\r\n", fitrange.usInWidth, fitrange.usInHeight, fitrange.usOutWidth, fitrange.usOutHeight);
        dbg_printf(3, "tmpgrabCtl N/M=%d/%d X=%d-%d Y=%d-%d\r\n", tmpgrabCtl.usScaleN, tmpgrabCtl.usScaleM,
                                                                  tmpgrabCtl.usStartX, tmpgrabCtl.usEndX,
                                                                  tmpgrabCtl.usStartY, tmpgrabCtl.usEndY);
        #endif
        MMPF_Scaler_SetEngine(MMP_TRUE, mainpipe, &fitrange, &tmpgrabCtl);
        MMPF_Scaler_SetLPF(mainpipe, &fitrange, &tmpgrabCtl);

        #if(DSC_SCALE_GRAB_IN_RAW_EN)
        if ( bRawPathPreview ) {
            MMPF_RAWPROC_CalcRawFetchTiming(mainpipe, MMPF_RAWPROC_DISTRIBUTION);
        }
        #endif
    return MMP_ERR_NONE;
}
//------------------------------------------------------------------------------
//  Function    : MMPF_Scaler_GetCurInfo
//  Description :
//------------------------------------------------------------------------------
MMPF_SCALER_ZOOM_INFO* MMPF_Scaler_GetCurInfo(MMPF_SCALER_PATH pathsel)
{
	return &m_scalerZoomInfo[pathsel];
}

#if PCAM_EN==0
//------------------------------------------------------------------------------
//  Function    : MMPD_Scaler_GetZoomInfo
//  Description :
//------------------------------------------------------------------------------
MMP_ERR MMPF_Scaler_GetZoomInfo(MMPF_SCALER_PATH pathsel, MMP_USHORT *usBaseN, MMP_USHORT *usCurrentN)
{
    *usBaseN = m_scalerZoomInfo[pathsel].usBaseN;
    *usCurrentN = m_scalerZoomInfo[pathsel].grabCtl.usScaleN;
    return MMP_ERR_NONE;
}
#endif

#if 0
//------------------------------------------------------------------------------
//  Function    : MMPF_Scaler_GetZoomOutPos
//  Description : in capture mode, sensor resolution is different with preview mode.
//               It must set the scale according to capture mode resolution
//------------------------------------------------------------------------------
MMP_ERR MMPF_Scaler_GetZoomOutPos(MMPF_SCALER_PATH pathsel, MMPF_SCALER_GRABCONTROL *SetgrabCtl)
{
    SetgrabCtl->usStartX = m_scalerZoomInfo[pathsel].grabCtl.usStartX;
    SetgrabCtl->usEndX = m_scalerZoomInfo[pathsel].grabCtl.usEndX;
    SetgrabCtl->usStartY = m_scalerZoomInfo[pathsel].grabCtl.usStartY;
    SetgrabCtl->usEndY = m_scalerZoomInfo[pathsel].grabCtl.usEndY;
    return MMP_ERR_NONE;
}
#endif

#if CAPTURE_BAYER_RAW_ENABLE
//------------------------------------------------------------------------------
//  Function    : MMPF_Scaler_GetScaleUpHBlanking
//  Description : get the exact Hblanking value when scaling up
//------------------------------------------------------------------------------
MMP_ERR MMPF_Scaler_GetScaleUpHBlanking(MMPF_SCALER_PATH pathsel, MMP_BYTE bPixelDelay, MMP_ULONG *pHBlanking)
{
	AITPS_SCAL  pSCAL    = AITC_BASE_SCAL;
	AIT_REG_B   *OprScaleCtl;
    MMP_ULONG   ScalerInWidth, tmp0, tmp1;
    MMP_USHORT  ScaleHM, ScaleHN, ScaleVM, ScaleVN;

    if (pathsel == MMPF_SCALER_PATH_0) {
        OprScaleCtl = &(pSCAL->SCAL_SCAL_0_CTL);

        ScalerInWidth = pSCAL->SCAL_GRAB_SCAL_0_H_ED - pSCAL->SCAL_GRAB_SCAL_0_H_ST + 1;

        ScaleHN = pSCAL->SCAL_SCAL_0_H_N;
        ScaleHM = pSCAL->SCAL_SCAL_0_H_M;
        ScaleVN = pSCAL->SCAL_SCAL_0_V_N;
        ScaleVM = pSCAL->SCAL_SCAL_0_V_M;
    }
    else if (pathsel == MMPF_SCALER_PATH_1) {
        OprScaleCtl = &(pSCAL->SCAL_SCAL_1_CTL);

        ScalerInWidth = pSCAL->SCAL_GRAB_SCAL_1_H_ED - pSCAL->SCAL_GRAB_SCAL_1_H_ST + 1;

        ScaleHN = pSCAL->SCAL_SCAL_1_H_N;
        ScaleHM = pSCAL->SCAL_SCAL_1_H_M;
        ScaleVN = pSCAL->SCAL_SCAL_1_V_N;
        ScaleVM = pSCAL->SCAL_SCAL_1_V_M;
    }
    else {
        OprScaleCtl = &(pSCAL->SCAL_SCAL_2_CTL);

        ScalerInWidth = pSCAL->SCAL_GRAB_SCAL_2_H_ED - pSCAL->SCAL_GRAB_SCAL_2_H_ST + 1;

        ScaleHN = pSCAL->SCAL_SCAL_2_H_N;
        ScaleHM = pSCAL->SCAL_SCAL_2_H_M;
        ScaleVN = pSCAL->SCAL_SCAL_2_V_N;
        ScaleVM = pSCAL->SCAL_SCAL_2_V_M;
    }

    if((ScaleHN > ScaleHM) || (ScaleVN > ScaleVM)){
        if (0) {//FIXME vsn_v2( *OprScaleCtl & SCAL_SCAL_DBL_FIFO) {
            tmp1 = ( ((MMP_ULONG)(ScaleHN * ScaleVN)/ (ScaleHM*ScaleVM)) - (MMP_ULONG)(bPixelDelay+1));
            tmp1 ++;
            tmp1 = ScalerInWidth *  tmp1;
            
            tmp0 = ScalerInWidth *( ((MMP_ULONG)(ScaleHN + ScaleHM -1)/ScaleHM)* ((MMP_ULONG)(ScaleVN + ScaleVM -1)/ScaleVM) - (MMP_ULONG)(bPixelDelay+1)) + 64 + 16;     //16 is tolerance 
            
            *pHBlanking = (tmp0 > tmp1) ?  tmp0 : tmp1;     
        }
        else {
            *pHBlanking = ScalerInWidth *((MMP_ULONG)(ScaleHN + ScaleHM -1)/ScaleHM)* ((MMP_ULONG)(ScaleVN + ScaleVM -1)/ScaleVM) + 64 + 16;     //16 is tolerance 
        }
    }
    else{
        *pHBlanking = 16;          // ISP line delay must have 3 pixel at least. 0x10 is tolerance 
    }

    return MMP_ERR_NONE;
}
#endif

#if 0
//------------------------------------------------------------------------------
//  Function    : MMPF_Scaler_EnableDNSMP
//  Description : When change sensor resolution, enable downsample function before frame enter scale
//------------------------------------------------------------------------------
MMP_ERR MMPF_Scaler_EnableDNSMP(MMPF_SCALER_PATH pathsel, MMP_BYTE bDownSample)
{
    AITPS_SCAL   pSCAL    = AITC_BASE_SCAL;

    if (pathsel == MMPF_SCALER_PATH_0) {
    	pSCAL->SCAL_DNSAMP_SCAL_0_H = bDownSample;
    	pSCAL->SCAL_DNSAMP_SCAL_0_V = bDownSample;
    }
    else if (pathsel == MMPF_SCALER_PATH_1) {
    	pSCAL->SCAL_DNSAMP_SCAL_1_H = bDownSample;
    	pSCAL->SCAL_DNSAMP_SCAL_1_V = bDownSample;
    }
    else {
    	pSCAL->SCAL_DNSAMP_SCAL_2_H = bDownSample;
    	pSCAL->SCAL_DNSAMP_SCAL_2_V = bDownSample;
    }

    return MMP_ERR_NONE;
}
#endif


/** @brief The function calculates the best grab parameter.

The function calculates the best grab parameter..
@param[in] fitrange the fit range parameters
@param[out] grabctl the grab control parameters
@return It reports the status of the operation.
*/
MMP_ERR MMPF_Scaler_GetBestFitScale(MMPF_SCALER_FIT_RANGE *fitrange,
                                               MMPF_SCALER_GRABCONTROL *grabctl)
{
    MMP_USHORT  x_scale, y_scale;

    grabctl->usScaleM = fitrange->usFitResol;

    y_scale = (fitrange->usOutHeight * grabctl->usScaleM + fitrange->usInHeight - 1) / fitrange->usInHeight;
    x_scale = (fitrange->usOutWidth * grabctl->usScaleM + fitrange->usInWidth - 1) / fitrange->usInWidth;

	if ((fitrange->usOutHeight > fitrange->usInHeight) || ( fitrange->usOutWidth > fitrange->usInWidth)) {
		// scale up case
		if (fitrange->fitmode == MMPF_SCALER_FITMODE_OUT) {
	    	while ((((fitrange->usInHeight - 1) * y_scale + grabctl->usScaleM - 1) / grabctl->usScaleM)
	    			< fitrange->usOutHeight)
    			y_scale++;
	    	while ((((fitrange->usInWidth - 1) * x_scale + grabctl->usScaleM - 1) / grabctl->usScaleM)
	    			< fitrange->usOutWidth)
    			x_scale++;
		}
		else {
	    	while ((((fitrange->usInHeight - 1) * y_scale + grabctl->usScaleM - 1) / grabctl->usScaleM)
	    			> fitrange->usOutHeight)
    			y_scale--;
	    	while ((((fitrange->usInWidth - 1) * x_scale + grabctl->usScaleM - 1) / grabctl->usScaleM)
	    			> fitrange->usOutWidth)
    			x_scale--;
		}	    		
	}
	else {
		// scale down case
		if (fitrange->fitmode == MMPF_SCALER_FITMODE_OUT) {
		    while (((fitrange->usInHeight) * y_scale) < (fitrange->usOutHeight * grabctl->usScaleM))
    			y_scale++;
		    while (((fitrange->usInWidth) * x_scale) < (fitrange->usOutWidth * grabctl->usScaleM))
	    		x_scale++;
		}
		else {
	    	while (((fitrange->usInHeight) * y_scale) > (fitrange->usOutHeight * grabctl->usScaleM))
    			y_scale--;
	    	while (((fitrange->usInWidth) * x_scale) > (fitrange->usOutWidth * grabctl->usScaleM))
    			x_scale--;
		}	    		
	}

    if (fitrange->fitmode == MMPF_SCALER_FITMODE_OUT) {
		if (x_scale > y_scale) {
       	   	grabctl->usScaleN = x_scale;
		}
       	else {
       	   	grabctl->usScaleN = y_scale;
       	}
   	}
	else {
       	if (x_scale > y_scale) {
   		 	grabctl->usScaleN = y_scale;
       	}
        else {
   	        grabctl->usScaleN = x_scale;
       	}
   	}

    if (x_scale > grabctl->usScaleM || y_scale > grabctl->usScaleM) {
		if (fitrange->fitmode == MMPF_SCALER_FITMODE_OUT) {
	    	grabctl->usStartX = ((fitrange->usInWidth - 1) * grabctl->usScaleN / grabctl->usScaleM
		    	                    - fitrange->usOutWidth) / 2 + 1;
	    	grabctl->usStartY = ((fitrange->usInHeight - 1) * grabctl->usScaleN / grabctl->usScaleM
								    - fitrange->usOutHeight) / 2 + 1;
		    grabctl->usEndX = grabctl->usStartX + fitrange->usOutWidth - 1;
		    grabctl->usEndY = grabctl->usStartY + fitrange->usOutHeight - 1;
		}
		else {
    	    grabctl->usStartX = 1;
       		grabctl->usStartY = 1;
		    grabctl->usEndX = ((fitrange->usInWidth - 1) * grabctl->usScaleN + grabctl->usScaleM - 1) / grabctl->usScaleM;
	    	grabctl->usEndY = ((fitrange->usInHeight - 1) * grabctl->usScaleN + grabctl->usScaleM - 1) / grabctl->usScaleM;
		}				    
	}
    else {
		if (fitrange->fitmode == MMPF_SCALER_FITMODE_OUT) {
        	grabctl->usStartX = (fitrange->usInWidth * grabctl->usScaleN / grabctl->usScaleM
   	                            - fitrange->usOutWidth) / 2 + 1;
        	grabctl->usStartY = (fitrange->usInHeight * grabctl->usScaleN / grabctl->usScaleM
                                - fitrange->usOutHeight) / 2 + 1;
		    grabctl->usEndX = grabctl->usStartX + fitrange->usOutWidth - 1;
    		grabctl->usEndY = grabctl->usStartY + fitrange->usOutHeight - 1;
		}
		else {
	        grabctl->usStartX = 1;
       		grabctl->usStartY = 1;
		    grabctl->usEndX = fitrange->usInWidth * grabctl->usScaleN / grabctl->usScaleM;
	    	grabctl->usEndY = fitrange->usInHeight * grabctl->usScaleN / grabctl->usScaleM;
		}	    	
	}

    return  MMP_ERR_NONE;    
}

//------------------------------------------------------------------------------
//  Function    : MMPD_Scaler_SetEnable
//  Description : 
//------------------------------------------------------------------------------
/** @brief The function enables or disables an icon on the display device

The function enables or disables icon with the specified icon ID on the display device. It is implemented
by programming Icon Controller registers.

  @param[in] usPipeID the IBC ID
  @param[in] bEnable enable or disable IBC
  @return It reports the status of the operation.
*/
MMP_ERR MMPF_Scaler_SetEnable(MMPF_SCALER_PATH pathsel, MMP_BOOL bEnable)
{
    AITPS_SCAL  pSCAL = AITC_BASE_SCAL;
    AIT_REG_B   *OprScalCtl;

	//MMPD_System_EnableClock(MMPD_SYSTEM_CLK_MODULE_SCAL, MMP_TRUE);

    if (pathsel == MMPF_SCALER_PATH_0) {
        OprScalCtl = &(pSCAL->SCAL_SCAL_0_CTL);
    }
    else if (pathsel == MMPF_SCALER_PATH_1) {
        OprScalCtl = &(pSCAL->SCAL_SCAL_1_CTL);
    }
    else {
        OprScalCtl = &(pSCAL->SCAL_SCAL_2_CTL);
    }

    if (bEnable == MMP_TRUE) {
        (*OprScalCtl) |= SCAL_SCAL_PATH_EN;
    }
    else {
        (*OprScalCtl) &= ~SCAL_SCAL_PATH_EN;
    }

	//MMPD_System_EnableClock(MMPD_SYSTEM_CLK_MODULE_SCAL, MMP_FALSE);

	return	MMP_ERR_NONE;	
}

/** @brief The function set the LPF coefficient according to the grab control
		
The function calculates the best grab parameter..
@param[in] pathsel the scaling path in Scaler
@param[in] grabctl the grab control parameters
@return It reports the status of the operation.
*/
MMP_ERR MMPF_Scaler_SetPath(MMPF_SCALER_SOURCE source, MMPF_SCALER_PATH pathsel)
{
    AITPS_SCAL  pSCAL = AITC_BASE_SCAL;

	//MMPD_System_EnableClock(MMPD_SYSTEM_CLK_MODULE_SCAL, MMP_TRUE);

    switch (source) {
    case MMPF_SCALER_SOURCE_ISP:
        if (pathsel == MMPF_SCALER_PATH_0) {
            //ctl_reg &= ~(SCAL_LPF_PATH_SEL_MASK | SCAL_SCAL0_PATH_SEL_MASK);
            //ctl_reg |= (SCAL_ISP_2_LPF | SCAL_LPF_2_SCAL0);
            pSCAL->SCAL_PATH_CTL &= ~SCAL_GRA_2_SCAL0;
        }            
        else if (pathsel == MMPF_SCALER_PATH_1) {
            //ctl_reg &= ~(SCAL_LPF1_PATH_SEL_MASK | SCAL_SCAL1_PATH_SEL_MASK);
            //ctl_reg |= (SCAL_ISP_2_LPF1 | SCAL_LPF_2_SCAL1);
            pSCAL->SCAL_PATH_CTL &= ~SCAL_GRA_2_SCAL1;
        }
        else {
            pSCAL->SCAL_PATH_2_CTL &= ~SCAL_GRA_2_SCAL2;
        }
        break;
    #if (CHIP == P_V2)
    case MMPF_SCALER_SOURCE_JPG:
        if (pathsel == MMPF_SCALER_PATH_0) {
            ctl_reg &= ~(SCAL_SCAL0_PATH_SEL_MASK|SCAL_LPF_PATH_SEL_MASK);
            ctl_reg |= SCAL_JPG_2_LPF;
        }
        else if (pathsel == MMPF_SCALER_PATH_1) {
            ctl_reg &= ~(SCAL_SCAL1_PATH_SEL_MASK|SCAL_LPF1_PATH_SEL_MASK);
            ctl_reg |= SCAL_JPG_2_LPF1;
        }
		break;
    #endif
    case MMPF_SCALER_SOURCE_GRA:
        if (pathsel == MMPF_SCALER_PATH_0) {
            //ctl_reg &= ~(SCAL_SCAL0_PATH_SEL_MASK|SCAL_LPF_PATH_SEL_MASK);
            //ctl_reg |= SCAL_GRA_2_LPF;
            pSCAL->SCAL_PATH_CTL |= SCAL_GRA_2_SCAL0;
        }
        else if (pathsel == MMPF_SCALER_PATH_1) {
            //ctl_reg &= ~(SCAL_SCAL1_PATH_SEL_MASK|SCAL_LPF1_PATH_SEL_MASK);
            //ctl_reg |= SCAL_GRA_2_LPF1;
            pSCAL->SCAL_PATH_CTL |= SCAL_GRA_2_SCAL1;
        }
        else {
            pSCAL->SCAL_PATH_2_CTL |= SCAL_GRA_2_SCAL2;
        }
        break;        
    }

	//MMPD_System_EnableClock(MMPD_SYSTEM_CLK_MODULE_SCAL, MMP_FALSE);

    return  MMP_ERR_NONE;    
}

MMP_ERR MMPF_Scaler_CheckZoomComplete(MMP_BOOL *bComplete)
{
    if (MMPF_HIF_GetCmdStatus(IMAGE_UNDER_ZOOM))
        *bComplete = MMP_FALSE;
    else
        *bComplete = MMP_TRUE;
    
    return MMP_ERR_NONE;
}

MMP_ERR MMPF_Scaler_CheckPanTiltComplete(MMP_BOOL *bComplete)
{
    if (MMPF_HIF_GetCmdStatus(IMAGE_UNDER_PANTILT))
        *bComplete = MMP_FALSE;
    else
        *bComplete = MMP_TRUE;
    
    return MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Scaler_SetPixelLineDelay
//  Description : Set scaler pixel and line delay
//------------------------------------------------------------------------------
/** @brief Set scaler pixel and line delay. Pixel and line delay only useful when scaling up
*/
MMP_ERR MMPF_Scaler_SetPixelLineDelay(MMPF_SCALER_PATH pathsel, MMP_UBYTE ubPixelDelay, MMP_UBYTE ubLineDelay)
{
    AITPS_SCAL  pSCAL	= AITC_BASE_SCAL;
    
    if(pathsel == MMPF_SCALER_PATH_0){
        pSCAL->SCAL_P0_PIXL_DELAY = ubPixelDelay;
        pSCAL->SCAL_P0_LINE_DELAY = ubLineDelay;
    }
    else if(pathsel == MMPF_SCALER_PATH_1){
        pSCAL->SCAL_P1_PIXL_DELAY = ubPixelDelay;
        pSCAL->SCAL_P1_LINE_DELAY = ubLineDelay;
    }
    else if(pathsel == MMPF_SCALER_PATH_2){
        pSCAL->SCAL_P2_PIXL_DELAY = ubPixelDelay;
        pSCAL->SCAL_P2_LINE_DELAY = ubLineDelay;
    }
    
	return MMP_ERR_NONE;
}

/// @}
